Lazy Instantiation of the Spring MVC DispatcherServlet? - java

Is there a way for me to instantiate the Spring MVC DispatcherServlet in code rather put it in the web.xml and have it be instantiated by the web server?
The reason for this is that I want to check a memCache to see if I have already recently rendered the page that is being requested and if so just return from the memCache, rather than going through Spring MVC and the controllers.
The ~2 second instantiation of the DispatcherServlet is significant because I am using Google App Engine and that might end up being an additional 2 seconds the user has to wait for their page.
I have tried
dispatcherServlet = new DispatcherServlet();
dispatcherServlet.init();
dispatcherServlet.service(request, response);
but I get this exception on the init call:
[java] java.lang.NullPointerException
[java] at org.springframework.web.servlet.HttpServletBean$ServletConfigPropertyValues.<init>(HttpServletBean.java:196)
[java] at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:114)
Basically, what I'm looking for is a way to instantiate a servlet in code without having to specify it in web.xml and not have to call
getServletConfig().getServletContext().getServlet("dispatcherServlet");

DispatcherServlet is a servlet, so you should call init(ServletConfig) instead of init() to initialize it.

Unless Google App Engine does something really weird, the DispatcherServlet is only instantiated once, on application startup.
If you want to cache page response as you mention, I would suggest implementing this as a HandlerInterceptor (which you can apply to any URL pattern you like), which gives you hooks to plug in logic in either pre- or post-invocation of your controller.

Related

How does spring come to know about the new request or session?

I know in a web application, for every request it gets, spring creates a new instance of the bean in ints container.
I want to know how does spring differentiate between the requests and create new instances of bean accordingly?
This work is done by Request context listener where it takes the decision of instantiating beans based on incoming http request and discarding them once their life cycle is over. Session , Request scope beans are only relevant if the application context web aware, if otherwise IllegalStateException will be thrown.
And also refer -
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-scopes-other

Multi DispatcherServlets in Spring MVC (Java Config)

I'm just new into Spring Framework tech and I'm making a website with few WebServices(Webstore, social media site etc.) included. What I want for it, is that every webservice would have it owns DispatcherServlet with own ViewResolver. So the structure of my projects looks like:
The Main site - DispatcherServlet #1 mapping only to http://example.com (yeah, i know i could just use static html site but it's for learning purposes.
Webservice no.1 e.g Webstore - DispatcherServlet #2 mapping only to
/webstore/*
Webservice no.2 e.g Social media site - DispatcherServlet #3 mapping only to /social/*
In configuration I'm using Java Classes, so what I did was:
Firstly I've Created AppConfig class that extends WebMvcConfigureAdapter and
implements ViewResolver for main site views. Next I've created An AppInitializer class which extends AbstractAnnotationConfigDispatcherServletInitializer class and inside of it I've configured RootConfigClass and servlet mapping
Secondly I've had problem - namely I couldn't create another class for Dispatcher Servlet #2 (couldn't have two classes which extended AbstractAnnotationConfigDispatcherServletInitializer ), what I've found was creating class which would implement an interface WebApplicationInitializer. Which I did and finally had working Second DispatcherServlet
Thirdly I've reapeted steps from second point and had Three working Dispatcher Servlets(in theory...).
I could access my main site via DispatcherServlet #1
(http://example.com)
I could access my webstore main site via DispatcherServlet #2 (http://example.com/webstore)
and I could access my webservice via DispatcherServlet #3(http://example.com/social)
but after all, when I've created another view pointing e.g. to login section (http://example.com/webstore/login) It didn't work at all. The errors said that Dispatcher Servlet #1 couldn't handle mapping request, where the address should be tied with Dispatcher Servlet #2. What I did to resolve this problem was changing The Dispatcher Servlet #2 configuration class part of servlet mapping from servlet.addMapping("/webstore/"); to servlet.addMapping("/webstore/*"); which I've read is not the best idea but It worked.
The problem appears when I would type address that Controller doesn't handle(doesn't exists) like (http://example.com/webstore/thisaddressdoesntexists), the view controller gives me back main default view from http://example.com/webstore, instead of 404 not found page. This is not the behavior I've intented to implement. Besides that little 'feature', everything works fine. All specyfic request are served with their specyfic DispatcherServlet. Finnal questions are:
How to prevent from loading default view, in this case scenario, when I'm pointing to non-existing url and load error code sites?
Is my concept even good at all? I mean using classes which implements WebApplicationInitializer for using more DispatcherServlets or there is another way? I'm only talking about Java-Based Config Classes, no xmls.
Is my concept even good at all? I mean using classes which implements
WebApplicationInitializer for using more DispatcherServlets or there
is another way? I'm only talking about Java-Based Config Classes, no
xmls.
For multiple servlets you need to have a single class which implements WebApplicationInitializer and there provide contextLoader class with all beans for the root context and define a separate class with all the beans for each servlet (usualliy the class which extends WebAppConfigurer). You also need to provide a mapping for each individual servlet. Have a look here how it's done as an example (the last 2 responses)
As regards to
Is my concept even good at all?
Why do you want to have three separate servlets? Are these three different apps bundled together? If that's the case I wouldn't put them in the same package but make three 3 different apps. You can also use a single Dispatchetservlet which maps to every url and have separate controllers for each component. That will reduce the complexity of the whole project. So it could be either way. Without knowing more about what you are trying to do no one can say it's right or wrong.
How to prevent from loading default view, in this case scenario, when
I'm pointing to non-existing url and load error code sites?
For error handling page have a look here. You would normally use #ResponseStatus for a specific HTTP error code or #ExceptionHandler for a general purpose error. In both cases you would need to redirect to a default error page.

Should I be using #Controller classes when doing Spring web flow

It seems like I can do everything that the Controller class do inside Spring Web-Flow, for example decision making and switching from page to page. To my understanding, its the C inside the MVC model. Am I correct about this?
So my question is, is there any advantage to still include a Controller class when using Spring Web-Flow?
If you need access to the request and response, an appropriate design might still include a controller while also having a flow.xml. For example, if you had this code:
HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getNativeRequest();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getNativeResponse();
It's more intelligible to put that in a controller rather than a service.
Also, if you want to register a custom editor, it might make sense to have the controller have this logic in the initBinder() method.
Spring Web Flow uses the Spring MVC framework. The DispatcherServlet handles the request. A FlowHandlerMapping is used to map the request to a particular Web Flow.
Web Flow is to solve the problem involved with controller logic that spans multiple-page navigation (a pageflow, or wizard).
Web Flow can eliminate the need for specialized controller classes to accomplish following a path of page transitions/form updates along a predefined workflow. If you don't need to do this, you can save yourself a lot of configuration/complexity just by using MVC.

How to setThreadContextInheritable(true) via xml on Spring's dispatcherportlet and dispatcherservlet

I want to make the current request available to child threads without passing on the original request as method parameters through several layers. The application runs both as a servlet and as a portlet.
Normally, DispatcherServlet and DispatcherPortlet set the current request into a RequestContextHolder on the current thread. That way, a call thread has access to the current request. The request is not propagated to child threads.
In my case, the request spawns a subthread where it makes a ReST call using RestTemplate, and I need to access the original request in an ClientHttpRequestInterceptor that intercepts the RestTemplate. The request that is passed to intercept is useless, I need the original request that hit the server.
Both DispatcherServlet and DispatcherPortlet have a feature to pass on the RequestContext to child threads: setThreadContextInheritable(true). However, it seems not so easy to set that flag to true. There is no init-param which sets it, and usually you specify them in web.xml or portlet.xml.
Is there a way to customize a dispatcher portlet or servlet via their setters using xml configuration? The only way I found is to write a custom dispatcherservlet/portlet which sets the flag to true internally and use that in web.xml and portlet.xml.
There is no way to do this directly through XML configuration. You would need to do as you said and create a subclass of DispatcherServlet which internally calls setThreadContextInheritable(true).
The alternative is to perform your ServletContext configuration in Java. Spring provides a WebApplicationInitializer and a number of useful subtypes where you can register a customized DispatcherServlet (other servlets and filters).
You'd create your instance.
DispatcherServlet servlet = new DispatcherServlet(context);
servlet.setThreadContextInheritable(true);
and then register it
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);

FacesServlet and URL Mapping in Web.xml

HI,
We are declaring the FacesServlet and its URL mapping in the Web.xml. From my understanding,
FacesServlet loaded only once at the server startup.
URL mapping is used only when first time JSP application accessed from the external context.
One of the new learner for JSF has asked me the questions, these two things are used only once by the application. Is it true? Also is there any other way by not including in the web.xml?
What I should answer?
Updated
For example, I am accessing the application using the URL http://localhost:8080/webapp/index.jsf. When we are accessing this URL, FacesServlet invoked and view is rendered. The following is my question:
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
In faces-config.xml we are giving the navigation cases as follows:
to-view-id>failure.jsp /to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
FacesServlet loaded only once at the server startup.
Correct.
URL mapping is used only when first time JSP application accessed from the external context.
Incorrect. It's been tested on every incoming HttpServletRequest. How else should the container know which servlet to invoke?
Also is there any other way by not including in the web.xml?
If you're using a servletcontainer which supports Servlet 3.0, you can also do this by #WebServlet annotation. JSF 2.0, however, is designed to be backwards compatible with Servlet 2.5, so it doesn't ship with that annotation and you need to explicitly declare it in web.xml.
See also:
Servlets tag info page
Lifecycle of a JSP/Servlet webapplication
How servlets are initialized and used
Update as per the new series of questions (which should each belong in its own question, but ala)
In JSF, we never seen changing the URL in the address bar. In that case, how it is handling the new request with the same URL?
This happens only if under the covers a forward by RequestDispatcher#forward() takes place. In a forward, the servletcontainer basically reuses the same HTTP request/response for a view (JSP/XHTML page). It does not force/instruct the webbrowser to send a brand new request. On the other hand, the HttpServletResponse#sendRedirect() will instruct the client (the webbrowser) to fire a new GET request and thus the URL will change. You can force this in the JSF sice by adding <redirect/> to the <navigation-case>. Note that since this causes a new request, all request scoped beans of the initial request will be lost.
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
The FacesServlet knows its own url-pattern.
Yes. while loading your application container will load web.xml and will extract the data for
particular URL pattern to servlet . when request comes it checks from memory that for this pattern which servlet to invoke and then if servlet is already loaded it will take it from memory otherwise it will create an instance of servlet and it will invoke doGet() or doPost() depending on the request type.
and there is another way to delcare URL mapping as from JAVAEE-6 by annotation
something like
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.WebServlet;
#WebServlet(
name = "SimpleServlet",
urlPatterns = {"/login"},
initParams = {
#InitParam(name = "param1", value = "value1"),
#InitParam(name = "param2", value = "value2")}
)
public class SimpleServlet {
}
In faces-config.xml we are giving the navigation cases as follows:
<to-view-id>failure.jsp </to-view-id>
Why we need not give the view name as failure.jsf? We are just giving the *.jsp in the faces-config.xml. How it is handled internally?
it is view identifier not the URL FacesServlet will load that view upon invocation of that navigation case.

Categories