Servlet's RequestDispatcher.forward() method does not work - servlets

I have a Java Application which connects to a servlet using HttpURLConnection. The application embeds the parameters it wants to pass to the servlet in the url while connecting to it.Thus the servlet can access and process these parameters using its doGet(). I am through with this part (I can access the parameters and dispay them in the servlet).
Next what I want to do is pass these parameters from the servlet to a JSP. I'm using request.setAttribute() to do it. But even after RequestDispatcherObj.forward(request, response), the JSP doesn't open. I've even tried response.sendRedirect(url).
However if I run the servlet independently, both the above methods(forward() and sendRedirect()) work fine and the JSP page opens.
I wonder what am I doing wrong.
Thanks in advance for your help.
CODE:
Java App
serverAddress = new URL("http://localhost:8080/WebApp/ServletPath"+"?message1"+"="+message);
(HttpURLConnection)serverAddress.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept-Charset", charset);
connection.setReadTimeout(10000);
connection.connect();
Servlet
message = request.getParameter("message1");//working
request.setAttribute("message1", message);//to be read in the jsp
url="/index.jsp";
RequestDispatcher dispatcher=getServletContext().getRequestDispatcher(url);
dispatcher.forward(request, response);//Works when servlet is run independently but not when the servlet is called from the App
}

HttpURLConnection is not used to change what the browser connects to and displays. It's used to create a HTTP connection in the Java application itself.
When a Java program connects to a URL and reads the response, the browser doesn't know about it, and won't magically display anything. By connecting to a URL in your Java app, you do the same thing as what the browser does, but in your own program. So you might read the response from the connection, and display what the webapp has sent.

Related

Disable access to a Servlet

I'm developing a WebApp using JavaEE and I use a servlet to test some stuff.
Currently, my WebApp is set as when I go to my local url localhost:8080/myApp/test , I can run my test Servlet.
My plan is to deploy my project to a Web and I want to disable the Servlet, but not delete it. I mean, if in the future I visit my remote server via URL www.myNewWeb.com/test , I would like it throws an error od do nothing.
How could I do that?
There are many possible options here:
Option 1
Remove the mapping (annotation #WebServlet or url mapping entry in web.xml). In this case, any attempt to call this servlet will end with an error generated by the JEE container of your choice. It will try to map the servlet to URL, will obviously fail and throw an exception
The obvious drawback of this method is that you need to change the deployment configuration and if you'll want to run the same artifact in another envrironment where this servlet should work you won't be able to do so.
Option 2
Create some kind of configuration, load this configuration along with your application.
In the doGet (just for the sake of example) method do something like this:
public void doGet(request, response) {
if(config.isTestServletEnabled()) { // this is where the data gets read from configuration that I've talked about before
// do your regular processing here
}
else {
// this will happen when the servlet should not be activated
// throw an exception, return HTTP error code of your choice, etc
}
}
This way doesn't have a drawback of the first method that I've explained above, however involves some code to be written.

How to pass an Object from a Servlet to JSR-356 WebSocket

I have a JSP-type servlet that registers a WebSocket Endpoint with the Servlet container.
I want to pass a reference of that servlet, and/or some of its objects, to the WebSocket Endpoint, so that I can use the code from that servlet, e.g. for Authentication or Session management (the servlet has its own non-Java EE Session management).
I was hoping that I could set some attribute somewhere when I call addEndpoint() on ServerContainer, because at that point I have access to the objects that I want to use later, but none of the classes that I've seen at that point have an attribute collection, e.g.
objectThatWillBeAvailableAtWebSocket.addAttribute("some.custom.object", someObject);
By the time my code reaches an ServletRequestListener, ServerEndpointConfig.Configurator, or the registered Endpoint, I do not have any reference to the original servlet that added the Endpoint.
How can I pass an Object to the WebSocket servlet? I'm running my test code in Embedded Jetty, but I'm aiming for Container-agnostic code.

Invoking HTTPS webservice from flex

I have an https .net webservice. Invoking web methods using tools like soap UI works fine. I am unable to invoke the webmethod from flex. My WSDL loads up fine in flex.
On deployment my flex application and the webservice are on the same server. When use the machine url and access from within the server it works fine, but not when I use the https url for the flex application.
Eg - http://machinename/flex/flexApp.html works fine with https://publicname/wservice/ws.asmx but https://publicname/flex/flexapp.html fails to work.
I have the crossdomain policy in place with full access and also I have a valid SSL certificate on the server.
When I make the call from my local machine in debug mode I see the following in Fiddler-
The WSDL call goes fine and returns back correctly and the Protocol is shown as HTTPS where as the webmethod call following it shows the protocol as HTTP and returns back with the error -
I have been stuck on this for quite some time. Any help is greatly appreciated.
Thanks,
Nikhil.
Here is my Flex code that calls it:
//business delegate
public function BusinessDelegate(responder : IResponder):void
{
_responder = responder;
_service = ServiceLocator.getInstance().getService("sqlWebService");
_service.loadWSDL();
}
//Login User
public function Login(userId:String,password:String):void
{
var asyncToken:AsyncToken = _service.LoginUser(userId,password);
asyncToken.addResponder(_responder);
}
and the service locator has the following tag where I set the URL from outside as https://....
<mx:WebService
id="sqlWebService"
useProxy="false"
concurrency="multiple"
showBusyCursor="true"
wsdl="{Url}"/>
I finally was able to resolve this problem by replacing the code where I call the Flex WebService object with the specific generated classes for the webservice.
I generated classes for the webservice using Import WebService(WSDL) and was setting the url on the main class on run time as https://.....
and it works like a charm...and I see that in fiddler it shows me correctly going out as HTTPS instead of the HTTP.
Here is what helped me -
http://livedocs.adobe.com/flex/3/html/help.html?content=security2_15.html
Comment by nated.
Thanks Flextras.com for pointing me to right direction.
Resolved.
If using WCF service and WebService in Flex, use
service.svc?wsdl for HTTP and
service.svc/wsdl?wsdl for HTTPS,

IIS7 Application Request Routing (arr reverse proxy) combined with managed module - time out

I am trying to build a proxy that would serve requests to an internal site (hiding the origin) but at the same time inspect the packets and asynchronously post-process them.
E.g. let's say all SOAP calls to http://www.foo.com will go to http://192.168.1.1, and at the same time be stored in a DB for post analysis. The internal server is a black box, so changing something on it is out of this question scope.
Anyway, I have configured ARR, with reverse proxy, made URL rewrite filter with wildcards, all works flawless. Then, I tried to add an managed HttpModule written in C#, and hooked to Application_BeginRequest and Application_EndRequest. I am able to access request headers, response headers on end request (app pool being in integrated mode) and even able to read response content from the outputstream by setting a filter on Response.Filter, that caches all writes in an additional memory stream.
The problem is that the moment I try to read (inside the module BeginRequest handler) the input stream from the request, ARR stays a while and throws a
HTTP Error 502.3 - Bad Gateway The
operation timed out Handler
ApplicationRequestRoutingHandler
Error Code 0x80072ee2
So it times out.
Looking with Failed Request Tracing I see:
MODULE_SET_RESPONSE_ERROR_STATUS
Warning
ModuleName="ApplicationRequestRouting",
Notification="EXECUTE_REQUEST_HANDLER",
HttpStatus="502", HttpReason="Bad
Gateway", HttpSubStatus="3",
ErrorCode="2147954402",
ConfigExceptionInfo=""
SET_RESPONSE_ERROR_DESCRIPTION Warning
ErrorDescription="The operation timed
out"
Now any similar posts on the net didn't helped as this isn't a timeout error (proxy has 120 seconds setting, page answers in under 100 ms), and the moment I comment the code of the handler that tries to read FORM data or InputStream data, everything works as a charm.
Even if I set the position of the inputstream to 0 after reading it, I still get timeouts.
If I read the input stream on EndRequest, it gets 0 bytes, even if it was a POST request. (which is clearly wrong)
Does ARR has a bug in the fact that I try to read an input stream before it tries to re-route it?
Things used: Windows Server 2008 R2
IIS 7.5 ARR v2 .Net Framework 3.5
module
Ideas?
Thanks
/Cosmin
If you can switch to .Net Framework 4, there is a solution for this.
After you are done with your BeginRequest/EndRequest in your HttpModule event handler, add a call to HttpRequest.InsertEntityBody.
/* BeginRequest event: Executes before request is processed */
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpRequest request = application.Context.Request;
// Do something with request
DoMyOwnRequestProcessing(request);
// After you finish, make sure IIS gets the entity body
// For example, Application Request Routing needs this
request.InsertEntityBody();
}
Take a look at this on MSDN: HttpRequest.InsertEntityBody.
I know this is a year old question, but I just went through the same thing and found a solution. So, I'm posting it here for anyone else that runs into this.
In my case I only saw the timeout issue with POST requests.
It appears that the 2.0/2.1 ARR assumes that the input stream will be at the start of the posted data. However, the following code (for example) will break this assumption:
HttpContext context = HttpContext.Current;
HttpRequest request = context.Request;
string value = request.Params["Name"];
The key is how Params is described
Gets a combined collection of System.Web.HttpRequest.QueryString,
System.Web.HttpRequest.Form, System.Web.HttpRequest.ServerVariables,
and System.Web.HttpRequest.Cookies items."`
When the request is a POST, accessing Params will read the posted data from the input stream, invalidating ARR's assumption. As will reading from the input stream.
I knew the data I needed was in the query string, not the posted data, so I worked around this by accessing the QueryString instead of Params. This avoids reading the posted data and works fine for me.
string value = request.QueryString["Name"];
This issue appears to be fixed in ARR 2.5.
Upgrading ARR appears to be the only solution if you need to access posted data before handing off to ARR. The key is to let HttpRequest handle acquiring the data into Params. If you read it directly it will not work.
I just ran into this bug and your experiences helped me determine the root cause.
My main server is MVC based and it looks at the Request.Form values in the Application_BeginRequest method. If the form values are accessed ARR fails to forward the body of a HTTP POST request. GET requests will work fine since there is no body.
I have routes.IgnoreRoute ("Forum/{*pathInfo}"); as a registered route but ARR runs as a HttpModule and doesn't kick-in until later in the pipeline. That means my MVC based application is given the opportunity to access the content of the POST body which somehow prevents ARR from accessing the body itself and forwarding it to the proxy'd server.
Here is Cosmin's related post on the iis.net forums: ARR 2.0 BUG - combined with managed http module timeout on read inputstream
In my application I have all myserver.com/Forum/* requests being reverse proxy'd to a separate application on another server. So I simply checked the HttpContext.Current.Request.Url in my MVC application's Application_BeginRequest method to make sure it does not contain /Forum before accessing the Request.Form values. Once I did that the POST bodies made it through ARR just fine.
UPDATE: after further testing it appears that there are still problems with ARR as POST from non-authenticated users still fails. Instead of the main website being MVC I created a dummy IIS .NET 4.0 website with a single Default.html document. But I still ran into problems with POST requests and ARR. Then I switch the application pool to ASP.NET 2.0 and what do you know, it works. At this point I have to assume that something in the .NET 4.0 pipeline is accessing the input stream which prevents ARR from accessing the input stream itself in order to forward the POST body.
按照正常来说,再iis网站界面会有一个application request
routing cache 的 icon, 可以点击 设置timeout 但是这里没有显示
找到了 官方说明可以用命令行解决这个问题
https://blogs.iis.net/richma/502-3-bad-gateway-the-operation-timed-out-with-iis-application-request-routing-arr
​
blogs.iis.net
执行以下命令,然后重启下网站服务
进入到C:\Windows\System32\inetsrv 打开管理员命令行工具执行以下命令
appcmd.exe set config -section:system.webServer/proxy /timeout:"00:00:45" /commit:apphost
重启下网站服务
我写的原文地址
https://zhuanlan.zhihu.com/p/157557980

How do I get the host domain name in ASP .NET without using HttpContext.Current.Request?

I've got an ASP .Net application running on IIS7. I'm using the current url that the site is running under to set some static properties on a class in my application. To do this, I'm getting the domain name using this (insde the class's static constructor):
var host = HttpContext.Current.Request.Url.Host;
And it works fine on my dev machine (windows XP / Cassini). However, when I deploy to IIS7, I get an exception: "Request is not available in this context".
I'm guessing this is because I'm using this code in the static constructor of an object, which is getting executed in IIS before any requests come in; and Cassini doesn't trigger the static constructor until a request happens. Now, I didn't originally like the idea of pulling the domain name from the Request for this very reason, but it was the only place I found it =)
So, does anyone know of another place that I can get the host domain name? I'm assuming that ASP .Net has got to be aware of it at some level independent of HttpRequests, I just don't know how to access it.
The reason that the domain is in the request is...that's what's being asked for. For example these are a few stackexchange sites from http://www.stackexchangesites.com/:
http://community.ecoanswers.com
http://www.appqanda.com
http://www.irosetta.com/
If you ping them, you'll see they all point to the same IP/Web Server and be served by the same app (or multiple apps in this case, but the example holds if it was one big one)...but the application doesn't know which one until a host header comes in with the request asking the server for that site. Each request may be to a different domain...so the application doesn't know it.
If however it doesn't change, you could store it as an appSetting in the web.config.
Use global.asax or write a HttpModule and subscribe to start request events. You will have the request passed into your event handler.
Use this instead:
HttpRuntime.AppDomainAppVirtualPath
Or if you want the physical path:
HttpRuntime.AppDomainAppPath
For further reading:
http://weblogs.asp.net/reganschroder/archive/2008/07/25/iis7-integrated-mode-request-is-not-available-in-this-context-exception-in-application-start.aspx

Resources