Spring using different contexts and SpringBeanAutowiringSupport in jsp - java

I have the following problem. My multi module spring application is loading up two different contexts at startup.
Context one is loaded up with this code snippet.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
and the other one via the rest webservice
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/components_webservice.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Now I got a jsp using this command to use autowired beans inside the jsp.
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
This only makes it possible to autowire the beans defined in the main context. I can't autowire beans from the REST Servlet declared context. Is there a way to make this context available inside the jsp? I know one way would be to declare all the beans inside the main context, but I want them to keep separated.
Greetings,
smoothny

Dont put any logic inside your jsp. Autowire fields in your controllers and pass generated values to the model.

Related

Spring - how to load properties prior to context loader getting called

I would like to read the properties from my properties files in my custom contextLoadListener. However my listener class gets executed prior to spring loading the properties file. How do I get my 'rdbaccess.properties' loaded prior to the execution of my CustomContextLoaderListener class? Below is my relevant parts of the configuration.
In web.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
com.my.package.setup.CustomContextLoaderListener
</listener-class>
</listener>
In spring-servlet.xml
<context:component-scan base-package="com.my.package" />
<context:property-placeholder location="classpath:rdbaccess.properties" />
The ContextLoader(Listener) is the instance that initializes your Spring context. This has to be the very first thing happening in the lifecycle of your (Spring) application, at all. It's not possible that your properties get loaded before the context has initialized. You can't decorate your living room before you've built the house :)
However, regarding the name of your properties, you probably need to inject the database credentials into your beans. This issue can be resolved with another approach, which is a lot cleaner in my opinion, especially for applications that run in multiple environments.
Instead of keeping/putting the credentials in your classpath, you should configure properties that change for each environment (local, development, integration, production ...) right there. For example, if you run a Tomcat, then put a properties file into the conf directory containing your database credentials. You can access that file in your custom ContextLoaderListener and provide the properties to your beans through a class with a static properties map, for instance.
Try adding a custom context initializer to load your properties file, like so:
https://gist.github.com/rponte/3989915

how to load a class during start up in spring, I am new to spring

how can application itself be inserted in database during startup only once.
I already tried using #postconstruct to do this.
When using Spring the following are common usage scenario's.
If you are building a web application you add some configuration to web.xml, for example (example for Spring 3):
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
This makes sure the Spring application context in the file /WEB-INF/spring/dispatcher-config.xml is loaded when the web application is loaded by the container (e.g. Tomcat). Your application will in this case probably contain of controllers of some sort (classes which handle requests) and these can be set up in spring to be injected with dependencies from the application context.
If you are building a standalone application you need to start it using the main method as usual. To load the Spring application context you need to do something like this:
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
MyApplication app = (MyApplication )context.getBean("myApp");
app.doSomething();
This loads the application context from the classpath.

Spring MVC: Using #Autowire is getting references to different spring bean instances

I have a UserCredetnialsDatSourceAdapter defined in my Spring app context file. I also have a custom filter added to the Spring via the DelegatingFilterProxy.
This filter is using the #Autowire to get a reference to the DataSource Bean. I also #Autowire the DataSource in my DAO. When I debug I see different instance id's to the datasource in the Filter and DAO instances. Why are there 2 instances whenthese are singletons by default?
I also fired up jvisualvm and I looked at the heap and all my beans in my app context have 2 instances? Thanks for any insight maybe the bean pre/post processing has something do with it or maybe I should not be using #Autowire in a Filter. Any help is apprciated. Thanks!
EDIT
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/web-context.xml,/WEB-INF/config-context.xml</param-value>
</init-param>
Interesting I think I see what it going on. There are 2 instances because there are 2 contexts. One for the app and 1 for each request (Thread) I assume? Is there a way to specfiy which context to use? Maybe filter is not the answer and I will need to use AOP. Need to research how to inject a bean in #Aspect, if that is even possible.
Thanks!!
-Joe
You are importing your /WEB-INF/config-context.xml as part of your Root Application Context(one loaded up by ContextLoaderListener) as well as your Web Context(loaded by DispatcherServlet). You can probably remove it from the one for DispatcherServlet.

Singleton resources shared by several MVC controllers in Java

Is there a way to have a singleton resource used by multiple controllers?
We got 2 servlets, each one with its own application contexts: one-servlet.xml & two-servlet.xml and lib-context.xml with singleton bean "util".
Now, if we import lib-context.xml into each of 2 servlet contexts above, spring will create a separate application context for each servlet and we'll end up with 2 singletone objects.
Is there a way to configure application that only one singleton object will be created?
Yes. In your web.xml, load lib-context.xml with the ContextLoaderListener instead of loading it with the DispatcherServlet.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/lib-context.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
You can remove the imports from your servlet-specific app context configuration files.
All the DispatcherServlets will see not only the shared lib-context.xml above but also any contexts that they themselves load.
(You may need to adjust the param-value example I gave. That path is just an example.)

Why is my Spring ContextRefreshed event called twice?

I have a Spring ApplicationListener bean registered to listen for ContextRefreshed events. For some odd reason though, I get two calls to the onApplicationEvent(ContextRefreshedEvent) method at the completion of the context initialization. Is this normal behavior or is it indicative of a problem with my configuration? I'm using Jetty 8 for my Servlet container.
My relevant web.xml configuration is as follows
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring/spring-config.xml</param-value>
</context-param>
<servlet>
<servlet-name>Spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>Spring</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
Thanks!
Even though you did not specify a contextConfigLocation for your DispatcherServlet it still creates a child context and the second refreshed event is for that context. Use event.getApplicationContext() to find out which context the event is for.
it happened to me as well, on a different event-listener. (ApplicationListener<AuthenticationFailureBadCredentialsEvent>)
I suspected the ContextLoaderListener, and when I removed the declaration from the web.xml, the app was working properly. Then I had to figure out what is its purpose, of the ContextLoaderListener...
Role/Purpose of ContextLoaderListener in Spring?
the interesting answer there is:
ContextLoaderListener is optional. Just to make a point here: you can
boot up a Spring application without ever configuring
ContextLoaderListener ...just the basic minimum web.xml with
DispatcherServlet
It looks like bug.
https://jira.springsource.org/browse/SPR-6589
If you are using 3.0 try it on the latest available release which is 3.05.
I had this problem too but fixed it. I was injecting the dataSource into my DAO (and instantiating a JdbcTemplate with it)....but I also had a Spring bean configured for JDBCTemplate.
I should have been injecting my DAO with the jdbcTemplate...that avoids the duplicate.

Categories