Spring MVC Initializing an object - java

In my SpringMVC project I need a certain tactic to call a class which does parse a xml file which does own my RMI server ip & port & the url must be relative to servletContext url :
HttpServletRequest request;
request.getServletContext().getRealPath("/WEB-INF/LABLAB/RMI-Config.xml")
I want to load these classes when I start my application in tomcat not when I call a Controller Class because my application depend to my RMI so before anything else I have to parse my file & using the IP & PORT fields to start connecting to my RMI & then call the rmi method to do some stuffs later on ...
now
how I'm gonna do it ? please tell me how I can initialize an instance of HttpServletRequest & give an intial value when I'm not on the Controller classes as well .
Thank you

You are using Spring, then you can create a class and implement IntializingBean. If you want to get hold of ServletContext you can simple use #Autowired annotation in your initializing bean. For e.g.:
#Component
public class SomeBean implements InitializingBean {
#Autowired
private ServletContext context;
public void afterPropertiesSet() throws Exception {
String path = context.getRealPath("/WEB-INF/LABLAB/RMI-Config.xml");
//do something.
}
}
As per docs:
IntializingBean - Interface to be implemented by beans that need to
react once all their properties have been set by a BeanFactory.
Or take a look here how to do this using ServletContextListener.

You need to implement the ServletContextListener interface and refer to it from your web.xml:
<listener>
<listener-class>InitializingListener</listener-class>
</listener>
The interface has a contextInitialized(ServletContextEvent sce) method, in which you can call sce.getServletContext(), so you don't need a HttpServletRequest.
If this doesn't work out, because you also need to access some of your Spring beans from the initializing class, then forget about implementing the ServletContextListener interface, and do the following instead:
Instantiate your initialization class via Spring (make a bean of that type).
Make the class implement ServletContextAware. This will cause Spring to inject the ServletContext into your class.
Define an init method on that bean (use the init-method bean attribute, or define a #PostConstruct annotated method)
Make all your Controller beans depend on the initializing bean by using the depends-on bean attribute. As a result, the initialaizing bean will be created before any Controller bean.
Without the last step, it cannot be guaranteed that your controllers won't start processing requests before the initialization bean finishes its work. However, specifying the depends-on attribute on each and every controller bean is also problematic, especially that they are usually created by applying the #Controller annotation instead of xml configuration. A nice workaround is described in this post.

Related

spring-boot - Which piece of code actually register dispatcher servlet for springMVC?

I am trying to find out in spring-boot, which implementation of WebApplicationInitializer actually register the dispatcher servlet.
I didn't found any piece code from SpringBootServletInitializer or its parent types did that.
Instead, AbstractDispatcherServletInitializer does the job, but it's abstract, I can't find any of its concrete implementation with help of Eclipse.
So, which piece of code from which class is actually invoked to register the dispatcher servlet for springMVC?
This is a subsequent question of: How does spring-boot able to serve specific url?
Below is the description of Spring Boot initialization steps that eventually register DispatcherServlet.
Example Code
#EnableAutoConfiguration
public class TestSpring {
public static void main(String[] args) throws Exception {
SpringApplication.run(TestSpring.class, args);
}
}
Spring Boot Initialization Steps
Here are the steps:
SpringApplication.run() creates EmbeddedWebApplicationContext application context;
Calls its refresh() method;
Refresh process reads annotations of the starting class TestSpring. It looks for import annotations. EnableAutoConfiguration is one of them. For an import annotation the refresh process gets the corresponding class from the annotation value and invokes its selectImports() method;
In case of #EnableAutoConfiguration the corresponding class is EnableAutoConfigurationImportSelector whose selectImports() loads tons of other import selectors from the META-INF/spring.factories;
This process continues recursively. Also, all bean definitions, that are inside these import selectors, are read. I.e. it includes beans defined by a method with the #Bean annotation, i.e. beans that require the Spring context to call the corresponding method automatically to instantiate them;
The resfresh() continues and reaches onRefresh(), the createEmbeddedServletContainer() method is called inside;
Among read bean defitions at the previous step, beans implementing ServletContextInitializer are searched for and instantiated. One of them is the bean, defined by the DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration() method of ServletRegistrationBean type that extends ServletContextInitializer. As you can guess from the name of the class, such initializers add a given servlet (in this case DispatcherServlet) to a given ServletContext, when their onStartup() method is invoked;
A tomcat embedded server is created (not started completely yet). All found ServletContextInitializers at the previous step are passed to this tomcat initialization - this is where the onStartup() methods of those ServletContextInitializers are called and DispatcherServlet gets created and registered as servlet;
End of onRefresh() of application context;
The finishRefresh() is called where tomcat is finally started by TomcatEmbeddedServletContainer.start();
End of refresh() of application context and other final initialization steps;
The app is running.
When you look for something Spring Boot does during auto-configuration, you should look in the *AutoConfiguration classes. In this case, DispatcherServletAutoConfiguration.
If you want to deploy the Spring Boot application as a traditional WAR, then the Servlet 3.0 specification details how service providers can set it up so that the 3.0 compliant servlet container will automatically bootstrap any web assets (Servlet, Filter, ServletContextInitializer's) into the servlet container. The "magic" is accomplished in the spring-web dependency. If you un'jar it, you'll find file "spring-web/META-INF/services/javax.servlet.ServletContainerInitializer". Open the file and you'll see single line "org.springframework.web.SpringServletContainerInitializer". This class delegates to all classes that implement WebApplicationInitializer, more specifically their onStartup(ServletContext servletContext) method. There's one such concrete class I'm aware of in Spring Boot, namely SpringBootServletInitializer.

Why does adding Spring DI into a Jersey 1.19.1 make my resource a singleton?

My goal in this entire endeavor is to try and inject a data source into a resource that can change at runtime. I am trying to avoid having to bloat the logic inside my resource if at all possible.
This is a legacy application with Jersey 1.19.1 using Spring 4.1.9.RELEASE (spring-aop, spring-beans, spring-context, spring-core, spring-expression, spring-web)
So here is my example resource:
#Path("/test)
public class TestResource {
public TestResource(){
System.out.println("Constructor Hit");
}
}
If I run hit this resource I get the following output
...request...
Constructor Hit
...request...
Constructor hit
So, the resource is created everytime there is a request, great!
Now, I want to use spring to inject a bean into this resource, so I get the following class.
#Path("/test)
#Component
public class TestResource {
#Inject
public TestResource(MyBean test){
System.out.println("Constructor Hit");
}
}
Now I get the following output
Constructor hit
...request...
...request...
The resource is only created once (I'm guessing at Spring application creation time).
Is there a way to fix this? I believe it is because I annotate with #Component but I can't seem to get the injection part without that.
Spring's default scope is singleton. when you call prototype class in singleton, spring DI inject prototype class just once at instantiate time.
read this issue if you want the singleton bean get a new instance of the prototype bean at runtime.

Create servlet context without autowiring in spring

I have a singleton class and one its private members is ServletContext object.
I made it singleton to remove spring dependency since I am trying to write in pure java code.
public class Utils {
private static Utils utils = null;
public Utils() {
// Exists only to defeat instantiation.
}
public synchronized static Utils getInstance() {
if (utils == null) {
utils = new Utils();
}
return utils;
}
#Autowired
private ServletContext servletContext;
public void makeUtils() {
// output csv path
String outputFile = servletContext.getRealPath("/util");
}
}
But here servletContext will be null because I am creating the object of Utils class wherever I needed manually. Not by using #Autowired. So spring is not injecting the dependency. How can I solve this.
#Autowired is a spring annotation.
If you want something to happen in response to that annotation, then you need to use spring. If you want to remove the dependency on spring, then you can't use Autowired. You need to pick one - are you depending on spring for your wiring, or not?
Some solutions you could follow:
Using Spring
Make Utils a spring bean and inject it
Put Utils into your spring context (bean factory) and then inject it (using #Autowired, or another wiring strategy) into every other class that wants to use it.
Make Utils a spring bean and look it up.
There's really not much reason to do it this way, but if you want, you can get access to your spring bean factory (probably via the ApplicationContext) and lookup a bean by type using BeanFactory.getBean(Class<T>)
Use Spring to autowire an existing Utils object
Again, there's not many good reasons to do this, but if you have an instance of AutowireCapableBeanFactory (which you can get via ApplicationContext) then you can call autowireBean(Object existingBean) to get spring to wire up your #Autowired fields.
Note: My method/class references are from Spring 3.2 because it's what's open in my IDE right now. You may need to make adjustments if you have a different spring version)
Without Spring
Instantiate Utils within a Servlet (or Listener)
Create a configure method on Utils that takes the ServletContext.
Inside a Servlet (or a ServletContextListener) call that configure method to set the servletContext field on Utils.
Store a static global ServletContext
Create an object like ServletContextHolder that has a static field on which you can store the ServletContext
Inside a Servlet (or a ServletContextListener) call the setContext method on that holder set the servletContext field.
Inside Utils call ServletContextHolder.getContext()

Inject HttpServletRequest into Controller

As I know per default are controllers in Spring MVC singletons. HttpServletRequest passed offen to the controller handler method. And its ok, while HttpServletRequest is request-scoped, but I see often HttpServletRequest gets #Autowired into the controller field, like this:
#Controller("CMSProductComponentController")
#RequestMapping(CMSProductComponentController.CONTROLLER_PATH)
public class CMSProductComponentController {
#Autowired
private HttpServletRequest request;
}
Could be this a problem? And more general question: What happens if inject a reqeust-scoped component into a singleton?
No, for HttpServletRequest it will not be a problem and it shouldn't for other request scoped beans. Basically, Spring will generate a proxy HttpServletRequest that wraps some kind of ObjectFactory (RequestObjectFactory for HttpServletRequest) (YMMV) that knows how to retrieve the actual instance. When you use any of the methods of this proxy, they will delegate to that instance.
What's more, this is done lazily, so it won't fail at initialization. It will however fail if you try to use the bean when there is no request available (or if you haven't registered the RequestScope).
The following is in response to the comments and to clarify in general.
Regarding the proxy-mode attribute of #Scope or the XML equivalent, the default is ScopedProxyMode.NO. However, as the javadoc states
This proxy-mode is not typically useful when used with a non-singleton
scoped instance, which should favor the use of the INTERFACES or
TARGET_CLASS proxy-modes instead if it is to be used as a dependency.
With request scoped beans, this proxy-mode value will not work. You'll need to use INTERFACES OR TARGET_CLASS depending on the configuration you want.
With scope set to request (use the constant WebApplicationContext.SCOPE_REQUEST), Spring will use RequestScope which
Relies on a thread-bound RequestAttributes instance, which can be
exported through RequestContextListener, RequestContextFilter or
DispatcherServlet.
Let's take this simple example
#Component
#Scope(proxyMode = ScopedProxyMode.INTERFACES, value = WebApplicationContext.SCOPE_REQUEST)
public class RequestScopedBean {
public void method() {}
}
...
#Autowired
private RequestScopedBean bean;
Spring will generate two bean definitions: one for your injected bean, a singleton, and one for the request scoped bean to be generated on each request.
From those bean definitions, Spring will initialize the singleton as a proxy with the types of your target class. In this example, that is RequestScopedBean. The proxy will contain the state it needs to produce or return the actual bean when it is needed, ie. when a method is called on the proxy. For example, when
bean.method();
is called.
This state is basically a reference to the underlying BeanFactory and the name of the request-scoped bean definition. It will use these two to generate a new bean and then call method() on that instance.
The documentation states
The Spring IoC container manages not only the instantiation of your
objects (beans), but also the wiring up of collaborators (or
dependencies). If you want to inject (for example) an HTTP request
scoped bean into another bean, you must inject an AOP proxy in place
of the scoped bean. That is, you need to inject a proxy object that
exposes the same public interface as the scoped object but that can
also retrieve the real, target object from the relevant scope (for
example, an HTTP request) and delegate method calls onto the real
object.
All eagerly loaded request scoped beans, if implemented correctly, will be proxies. Similarly, request scoped beans that aren't eagerly loaded will either be proxies themselves or be loaded through a proxy. This will fail if there is no HttpSerlvetRequest bound to the current thread. Basically, a proxy is necessary somewhere in the bean dependency chain for request scoped beans.
What happens if inject a reqeust-scoped component into a singleton?
Try it and you'll get a BeanCreationException¹ during application context initialization. The error message clearly explains why this doesn't happen with HttpServletRequest:
Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
So obviously HttpServletRequest is a scoped proxy. If you want to use beans of smaller scopes in singletons they have to be proxies. The documentation elaborates about smaller scoped dependencies in Scoped beans as dependencies.
[1]: unless you didn't change the default behaviour for proxyMode, which is NO or try to inject it with #Lazy. The latter might result into a valid application context but might lead to request scoped beans acting like singletons (e.g. if a request scoped bean is injected into a singleton).

Spring #Autowired and WebApplicationContext in Tomcat

#Autowired works only once.
What to do to make it wire the bean every time the Servlet is recreated?
My web-app (Tomcat6 container) consists of 2 Servlets. Every servlet has private fields.
Their setters are marked with #Autowired
In the init method I use
WebApplicationContextUtils
...
autowireBean(this);
It autowires the properties marked with #Autowired once - during the initialization of the Servlet.
Any other session will see these fields values, they will not be rewired after the previous session is destroyed.
What to do to make them rewire them each time a Servlet constructor is called?
a) Put the autowiring into the constructor?
Or better 2) get a web app context and extract a bean from there?
There seems to be some misunderstanding about how the container works. Servlets are essentially singletons, you don't get a new servlet everytime someone calls the server. Storing state in private fields on a servlet is pretty much an error.
What is the scope and life-cycle of the stateful part of your request processing? If it's just the life of the request then you can take whatever on your servlet is stateful and move it into another class. Then you can define a prototype bean for that class and use getBean at the start of the request to get a new one. If you want to start getting fancy you could write a filter that puts a new bean into a ThreadLocal at the start of each request.
If your state needs to span multiple requests, you need to start keeping state or a key that points to the state storage on the web session, or look into using a conversation framework.
Try using scope as prototype for that bean #Scope("prototype")
You may try to use #Scope("session")

Categories

Resources