When using old-styled (extends *Controller) controllers before we often used return new ModelAndView(new RedirectView("/url")) to return redirects from a Spring controller.
After upgrading to Spring 4.0 (#Controller) we've started to use return "redirect:/url" to do the same from #RequestMapping-annotated methods. However we've noticed that Spring adds all model attributes to a resulting redirect URL. This is highly undesirable behavior for us.
What makes matters worse: since those are added to a "Location" HTTP header (standard for HTTP 302) this makes Tomcat to throw an the following exception:
Aug 11, 2014 2:42:31 PM org.apache.coyote.ajp.AjpProcessor process
SEVERE: Error processing request
java.lang.ArrayIndexOutOfBoundsException: 8192
at org.apache.coyote.ajp.AjpMessage.appendByte(AjpMessage.java:146)
One solution that comes to mind is clearing the model before every redirect, however this is rather cumbersome.
Is there a way to configure Spring not to add all model attributes to a redirect url?
Add ignore-default-model-on-redirect="true" to your <mvc:annotation-driven> tag.
In a new application, or if your application does not depend on the usage of model attributed on redirect, you should add ignore-default-model-on-redirect="true" to the <mvc:annotation-driven> tag as Aramir said.
If it concerns only few new methods where other need the legacy mode, you can add a RedirectAttribute parameter to your method. As soon as it exists, Spring uses it instead of the model to determine which attributes should be used in redirected URL.
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.
I am using Spring-MVC LightCouch and CouchDB and I have custom Views that need to be inserted into the DB on deployment. I have found the LightCouch has a method for pulling documents "from desk" as noted on their website:
DesignDocument designDoc = dbClient.design().getFromDesk("example");
Response response = dbClient.design().synchronizeWithDb(designDoc);
This Works good from within JAVA code, however I need to be able to do it in the Spring ApplicationContext.xml I have more than one so I would like to mimick the call of:
dbClient.dessign().synchronizeAllWithDB()
How would I do this in the bean definition of the ApplicationContext I already have this:
<bean id="dbClient" class="org.lightcouch.CouchDbClient" lazy-init="false" destroy- method="shutdown">
<constructor-arg value="couchdb.properties" />
</bean>
It seems you can't do it with Spring xml config, as the init method falls under a different instance; that is returned by the call to design() factory method. Maybe you can try Java code equivalence, i.e. #PostConstruct.
I ended up having to make a bean that synchronized the database on init and created that when the app starts
The familiar code:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My understanding is that /* maps to http://host:port/context/*.
How about /? It sure doesn't map to http://host:port/context root only. In fact, it will accept http://host:port/context/hello, but reject http://host:port/context/hello.jsp.
Can anyone explain how is http://host:port/context/hello mapped?
<url-pattern>/*</url-pattern>
The /* on a servlet overrides all other servlets, including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually, you'd like to use /* on a Filter only. It is able to let the request continue to any of the servlets listening on a more specific URL pattern by calling FilterChain#doFilter().
<url-pattern>/</url-pattern>
The / doesn't override any other servlet. It only replaces the servletcontainer's built in default servlet for all requests which doesn't match any other registered servlet. This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. The servletcontainer's built in default servlet is also capable of dealing with HTTP cache requests, media (audio/video) streaming and file download resumes. Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, which is not exactly trivial (JSF utility library OmniFaces has an open source example). This is thus also a bad URL pattern for servlets. As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's built in JSP servlet will be invoked, which is already by default mapped on the more specific URL pattern *.jsp.
<url-pattern></url-pattern>
Then there's also the empty string URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested. This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". I only have to admit that I'd intuitively expect the empty string URL pattern and the slash URL pattern / be defined exactly the other way round, so I can understand that a lot of starters got confused on this. But it is what it is.
Front Controller
In case you actually intend to have a front controller servlet, then you'd best map it on a more specific URL pattern like *.html, *.do, /pages/*, /app/*, etc. You can hide away the front controller URL pattern and cover static resources on a common URL pattern like /resources/*, /static/*, etc with help of a servlet filter. See also How to prevent static resources from being handled by front controller servlet which is mapped on /*. Noted should be that Spring MVC has a built in static resource servlet, so that's why you could map its front controller on / if you configure a common URL pattern for static resources in Spring. See also How to handle static content in Spring MVC?
I'd like to supplement BalusC's answer with the mapping rules and an example.
Mapping rules from Servlet 2.5 specification:
Map exact URL
Map wildcard paths
Map extensions
Map to the default servlet
In our example, there're three servlets. / is the default servlet installed by us. Tomcat installs two servlets to serve jsp and jspx. So to map http://host:port/context/hello
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Doesn't match any extensions, next.
Map to the default servlet, return.
To map http://host:port/context/hello.jsp
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Found extension servlet, return.
Perhaps you need to know how urls are mapped too, since I suffered 404 for hours. There are two kinds of handlers handling requests. BeanNameUrlHandlerMapping and SimpleUrlHandlerMapping. When we defined a servlet-mapping, we are using SimpleUrlHandlerMapping. One thing we need to know is these two handlers share a common property called alwaysUseFullPath which defaults to false.
false here means Spring will not use the full path to mapp a url to a controller. What does it mean? It means when you define a servlet-mapping:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
the handler will actually use the * part to find the controller. For example, the following controller will face a 404 error when you request it using /perfix/api/feature/doSomething
#Controller()
#RequestMapping("/perfix/api/feature")
public class MyController {
#RequestMapping(value = "/doSomething", method = RequestMethod.GET)
#ResponseBody
public String doSomething(HttpServletRequest request) {
....
}
}
It is a perfect match, right? But why 404. As mentioned before, default value of alwaysUseFullPath is false, which means in your request, only /api/feature/doSomething is used to find a corresponding Controller, but there is no Controller cares about that path. You need to either change your url to /perfix/perfix/api/feature/doSomething or remove perfix from MyController base #RequestingMapping.
I think Candy's answer is mostly correct. There is one small part I think otherwise.
To map host:port/context/hello.jsp
No exact URL servlets installed, next.
Found wildcard paths servlets, return.
I believe that why "/*" does not match host:port/context/hello because it treats "/hello" as a path instead of a file (since it does not have an extension).
The essential difference between /* and / is that a servlet with mapping /* will be selected before any servlet with an extension mapping (like *.html), while a servlet with mapping / will be selected only after extension mappings are considered (and will be used for any request which doesn't match anything else---it is the "default servlet").
In particular, a /* mapping will always be selected before a / mapping. Having either prevents any requests from reaching the container's own default servlet.
Either will be selected only after servlet mappings which are exact matches (like /foo/bar) and those which are path mappings longer than /* (like /foo/*). Note that the empty string mapping is an exact match for the context root (http://host:port/context/).
See Chapter 12 of the Java Servlet Specification, available in version 3.1 at http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.
I have two web applications.But only one among them includes Java servlet class.I want to access that servlet class from within the web.xml file of other application.Is it possible?.If yes,How will be it possible?.
You can't do that in the web.xml. You can however create a new servlet which in turn redirects/forwards the request to the servlet of the other webapplication. Redirecting is easy, just let the URL point to the particular servlet.
response.sendRedirect("/otherwebapp/theservlet");
Forwarding requires a bit more work. This is by default not possible due to security restrictions. First you need to configure the servletcontainer to enable cross context access between the webapplications in question. It's unclear which one you're using, so here's just a Tomcat targeted example so that you understand in what direction you should look for your own servletcontainer: for the both webapps, you need to set the crossContext attribute of the <Context> element to true:
<Context crossContext="true">
This way you can obtain the other context by ServletContext#getContext() inside a servlet:
ServletContext othercontext = getServletContext().getContext("/otherwebapp");
Finally you can forward the request through it as follows:
othercontext.getRequestDispatcher("/theservlet").forward(request, response);