Spring Web App - Simple JDBC Template Advice? - java

Quick question based on a spring web app i am creating.
How do you go about setting up the context of the application so that you do not need to set the datasource parameters for simpleJDBC all the time and can call getSimpleJDBCTemplate().queryfor.... and it be set up with the datasource.
This is how i currently have it and it seems to go against inversion of control that spring is meant to provide as this is in every dao!
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:ApplicationContext.xml");
DataSource dataSource = (DataSource) ac.getBean("dataSource");
SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
ApplicationContext
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:properties.properties"/>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<bean name="SimpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<context:annotation-config/>
</beans>
Latest Stack Trace from Tomcat log
13-Jan-2011 20:15:18 com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
ptc.jersey.spring
13-Jan-2011 20:15:18 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class ptc.jersey.spring.resources.LoginResource
13-Jan-2011 20:15:18 com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
13-Jan-2011 20:15:19 com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext
INFO: Using default applicationContext
13-Jan-2011 20:15:19 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.4 09/11/2010 10:30 PM'
13-Jan-2011 20:15:21 com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
at ptc.jersey.spring.daoImpl.UserDaoImpl.getUser(UserDaoImpl.java:43)
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>Jersey Spring Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>ptc.jersey.spring</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Spring Web Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
</web-app>
Any help would be great
Thanks
Chris

Why don't you declare the SimpleJdbcTemplate instance as well in the application context file?
For example with these bean declarations
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="dburl"/>
<property name="username" value="dbusername"/>
<property name="password" value="password"/>
</bean>
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
And in your web.xml to load the application context
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>

Declare the SimpleJdbcTemplate bean in the context:
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
and use it like this:
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:ApplicationContext.xml");
SimpleJdbcTemplate simpleJdbcTemplate = (SimpleJdbcTemplate) ac.getBean("jdbcTemplate");
or in a DAO:
#Autowired
private SimpleJdbcTemplate simpleJdbcTemplate;
It is thread-safe, and therefore reusable.

What I'd recommend is that you declare your DataSource as bean and also the classes which need it and use dependency injection to introduce the DataSource to your class. As an example, your bean definition could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="dataSource" class="...">
<!-- your dataSource config here -->
</bean>
<bean id="yourClassThatNeedsDataSource" class="com.stackoverflow.q4684102.Example">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
and the accompanying class
package com.stackoverflow.q4684102;
import javax.jdbc.DataSource;
import org.springframework.jdbc.core.simple.*;
public class Example implements YourDaoInterface {
private SimpleJdbcOperations jdbc;
public void setDataSource(DataSource ds) {
jdbc = new SimpleJdbcTemplate(ds);
}
// your DAO methods here
}
Why do it this way instead of creating a bean out of the SimpleJdbcTemplate itself?
No difference, really - some people like it the other way, some others like it this way - you wan't have a huge XML with loads of bean definitions for intermediate objects if you do it this way, that's for sure. That, of course, is up to you to decide on how you want to design your software.

If you create SimpleJdbcTemplate inside setDataSource then you are creating a template per Dao instance.
If you configure as a bean and inject into the Dao, then you can resuse the same template across the Daos - which is recommended, because its threadsafe.

Related

the parameter problem of getWebApplicationContext() in spring

? hello, there. I am a student from Taiwan.
Recently I am studying JavaSpring, and I start with HelloWorld sample.
my problem is:
In index.jsp, this statement
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(application);
I think it is used to register(or connect?) the ContextLoader in web.xml so that I could use it to get beans. But I would like to know that why I could only send "application" as a variable even I couldn't find any declaration of this variable in my program. How did that work without undefined error?
Even I entered the class it imported above, still has no found about this.
Here is the code that sample offer me that I should add to index.jsp file:
<%#page import="org.springframework.web.context.WebApplicationContext"%>
<%#page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%
WebApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(application);
%>
and my web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ctx_ut.xml</param-value>
</context-param>
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>
my bean setting ctx_ut.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>WEB-INF/hello.properties</value>
</property>
</bean>
<bean id="dataSource" class="spring01.HelloWorld" scope="request">
<property name="message" value="${hi}"></property>
</bean>
<bean id="seeyou" class="spring01.SeeYou" scope="request">
<constructor-arg value="${seeYou}" />
<constructor-arg ref="dataSource" />
</bean>
<bean id="goodbye" class="spring01.Goodbye" depends-on="seeyou"
init-method="init" scope="request">
<property name="helloWorld" ref="dataSource"></property>
<property name="message" value="${goodbye}"></property>
</bean>
</beans>
(I guess class file is not important here so I didn't put here, it's just some string setter and getter.)
Is there any concept I misunderstand or any document had described it? please tell me and share the link.
First ask, hope my problem is clear enough. Thanks.

#Autowired doesn't work in Spring and Vaadin integration

I'm trying to integrate Spring with Vaadin, but I can't use the #Autowired annotation in my Vaadin classes.
Firstly, I created the followed maven structure
This is my web.xml
<web-app>
<display-name>Vaadin Web Application</display-name>
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class> org.springframework.web.context.request.RequestContextListener </listener-class>
</listener>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>com.mycompany.config.AutowiringApplicationServlet</servlet-class>
<init-param>
<description>Vaadin UI to display</description>
<param-name>UI</param-name>
<param-value>com.mycompany.ui.MyUI</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
This is my application-context.xml
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost/vaadin" />
<property name="username" value="postgres" />
<property name="password" value="tobbis" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="persistenceUnitName" value="myUnit"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<jpa:repositories base-package="com.mycompany.repository"></jpa:repositories>
<context:annotation-config/>
<context:component-scan base-package="com.mycompany" />
Now I created my UserService that is within com.mycompany.services package
#Service
public class UserService {
public void saveUser(User user){
System.out.println("Test to Save");
}
}
And finally, I have my Panel where I want to inject the service
public class UserPanel extends VerticalLayout {
#Autowired
UserService service;
public UserPanel() {
// TODO Auto-generated constructor stub
Injector.inject(this);
service.saveUser();
}
}
but the result is always the same
Error creating bean with name 'com.mycompany.ui.UserPanel': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: com.mycompany.services.UserService com.mycompany.ui.UserPanel.service;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.aiem.services.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Try to declare your UserService at applicationContext.xml
<bean name="userService" class="com.mycompany.services.UserService"></bean>
As far as I know,
Injector.inject(this);
is not something from Spring, you may be mixing it with another framework.
Instead, I would make UserPanel a prototype-scoped Spring component (meaning it can be instantiated and autowired by Spring, but you remain responsible for it's lifecycle).
#Component
#Scope(SCOPE_PROTOTYPE)
public class UserPanel extends VerticalLayout {
Note that a new instance will be created anytime UserPanel is retrieved from the context (e.g. autowired in another object). It could be best to control the creation of instances yourself by explicitly invoking
context.getBean(UserPanel.class)
at the right time.
AnnotationConfigWebApplicationContext is not meant to be used with XML config. It is supposed to be used with the #Configuration annotated classes.
Since you're using an xml file for Spring config, then you should instead remove these lines from web.xml:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
And then by default Spring will use the XmlWebApplicationContext and pick up your xml file.
I have tried the same scenario than you. At the end, the solution is at the Vaadin documentation.
Seems that the problem is that we are using Vaadin context and not Spring context, and therefore we need to do the trick showed in the documentation (SpringHelper) to obtain any bean. Outside of the Spring context, the autowiring is not goint to work.
There is an addon for enabling autowiring via annotations: http://vaadin.xpoft.ru/.
Here is the link to the Vaadin site: http://vaadin.com/addon/springvaadinintegration. Hope it helps.

Spring singleton being called twice

getting some problem into my spring application.
I have very fairly simple spring beans, they are injected into various other spring beans. While debugging I found, they are being called twice, Constructor & #PostConstruct both called two times.
My application have no front end technology. Its simply for backend task related.
Spring Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
<context:component-scan base-package="com.green.integration" />
<!-- ######################################################## -->
<!-- EXPOSING SPRING BEAN VIA HTTPINVOKER SPRING REMOTING -->
<!-- ######################################################## -->
<bean name="/switch"
class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="SwitchController" />
<property name="serviceInterface"
value="com.green.ISwitchController" />
</bean>
<!-- Load in application properties reference -->
<bean id="applicationProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties" />
</bean>
<bean id="mongo" class="com.mongodb.Mongo">
<constructor-arg value="${mongo.server}" />
<constructor-arg value="${mongo.port}" />
</bean>
<bean id="morphia" class="com.google.code.morphia.Morphia">
</bean>
</beans>
Spring Bean Class
#Repository
public class TransactionDAO extends BasicDAO<Transaction, ObjectId> {
private Datastore datastore;
#Autowired
public TransactionDAO(Mongo mongo, Morphia morphia) {
super(mongo, morphia, "itransact");
morphia.map(Transaction.class);
// TO USE MONGO WITHOUT SECURITY
this.datastore = morphia.createDatastore(mongo, "itransact");
logger.debug("***** CONNECTED TO MONGODB SUCCESSFULLY *****");
this.datastore.ensureIndexes();
// this.datastore.ensureCaps();
}
}
Constructor "TransactionDAO" is being called twice.
I tried to watch call stack trace by
Throwable t = new Throwable();
System.out.println(t.getStackTrace()[1].toString());
and each time it showed the following
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
I just figured out the problem and special thanks to #Juan Alberto who give me hint to the problem.
Description: Actually I was giving the one applicationContext.xml file for both contextListner and dispatcher servlet. So 1st bean was initializing for spring core and 2nd time for spring dispatcher.
I spilt the configuration now, into applicationContext.xml and applicationContext-dispatcher.xml which have only their relevant configurations and my beans are initializing once properly.
Problematic Configs
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
Solved Configs
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-dispatcher.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
Actually your issue is that you may be defining the beans in the dispatcher servlet and also your spring context, the dispatcher provides a different context but It (a sub context I think) of the main context so the right way to do things is having your main context scan your "model classes" and the dispatcher just only scan for the controllers.
I hope this helps you.

Can't force Spring Web MVC 3.0 framework to work

I'm building a Web application with Java. Trying to integrate Spring Web MVC 3.0 framework. But I can't even force simply to show the page. I am using NetBeans 7.0 and Tomcat 6.0.
This is what I've got:
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
Dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="forum.web" />
<!--
Most controllers will use the ControllerClassNameHandlerMapping above, but
for the index controller we are using ParameterizableViewController, so we must
define an explicit mapping for it.
-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<!-- org.springframework.web.servlet.view.InternalResourceViewResolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
</beans>
Controller:
package forum.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
*
* #author
*/
#Controller
public class RegistrationController
{
#RequestMapping("/registration.htm")
public ModelAndView registrationWindow()
{
return new ModelAndView("registration");
}
}
XHTML page:
<tr id="log_reg">
<td>
Log in
</td>
<td></td>
<td>
Register
</td>
</tr>
Running this command I see index page:
http://localhost:8088/Forum/index.htm
On the page I click the link, what suppose to open registration page. But instead is I see HTTP 404 error.
The link:
http://localhost:8088/Forum/registration.htm
Found errors on NetBeans:
18-Jun-2011 14:45:19 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/index.htm] onto handler [org.springframework.web.servlet.mvc.ParameterizableViewController#1fb0fc2]
18-Jun-2011 14:45:20 org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'dispatcher': initialization completed in 1279 ms
18-Jun-2011 14:45:20 org.apache.catalina.core.StandardContext start
INFO: Container org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/Forum] has already been started
18-Jun-2011 14:45:35 org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/Forum/registration.htm] in DispatcherServlet with name 'dispatcher'
18-Jun-2011 14:51:53 org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/Forum/registration.htm] in DispatcherServlet with name 'dispatcher'
I can't release the cause of these errors. Code looks fine, in my opinion. I tried many things by this time.
Any help?
Best regards
Probably it's because you use both annotation mapping and SimpleUrlHandlerMapping.
Try to add bean:
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotat ion.DefaultAnnotationHandlerMapping">
</bean>
and add it as a handler to your urlMapping bean:
<property name="interceptors">
<list>
<ref bean="handlerMapping"/>
</list>
</property>
It's easier to use only one of them, especially annotation based controllers. At this case you have to throw out your urlMapping bean, and instead of indexController bean use simple class like:
#Controller
class PagesCtrl {
#RequestMapping("/index.htm")
ModelAndView index() {
ModelAndView mav = new ModelAndView("index")
return mav
}
}

problem with using spring beans from jsf managed bean

I have web application wich uses jsf 2.0 and spring 3.0
The problem is that: jsf managed beans can't use spring beans using dependency injection
There are my config files:
web.xml:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 1 </load-on-startup>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/calc/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-beans.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
faces-config.xml:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
<managed-bean>
<managed-bean-name>CalcBean</managed-bean-name>
<managed-bean-class>timur.org.bean.CalculatorConroller</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>hibernateUtil</property-name>
<value>#{hibernateUtil}</value>
</managed-property>
</managed-bean>
spring-beans.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost/timur"/>
<property name="username" value="postgres"/>
<property name="password" value="postgres"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>/mapping/service.xml</value>
<value>/mapping/city.xml</value>
<value>/mapping/timurovec.xml</value>
<value>/mapping/client.xml</value>
<value>/mapping/calendar.xml</value>
<value>/mapping/order.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="hibernateUtil" class="timur.org.util.HibernateUtil">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
CalculateController:
public class CalculatorConroller {
private HibernateUtil hibernateUtil;
public void setHibernateUtil(HibernateUtil hibernateUtil) {
this.hibernateUtil = hibernateUtil;
}
public String action() {
hibernateUtil.createAndStoreEvent("",new Date());
List<CityDomain> lc = hibernateUtil.getList();
for (int i=0; i<lc.size(); i++){
LogManager.getLogger(this.getClass()).debug(lc.get(i).getName());
}
return "success";
}
}
when i run my web application and call my controller action variable 'hibernateUtil' is null and there no exceptions. But i can get spring beans using:
hibernateUtil = (HibernateUtil) FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance()).getBean("hibernateUtil");
How can i get this spring bean using dependency injection?
Why don't you declare your faces managed bean in your spring-beans.xml ?
Maybe you will also need to add this in your faces-config:
<application>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
I am not 100 percent sure about this though because I am not at my workstation right now. But I think it has to be like the above.
So then you just move your "CalcBean" to spring-beans.xml and use it as before.
What you're missing is a way for JSF dependency injection to know about Spring and its beans. Just add this to your faces-config.xml:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
thanks very much for your answers.
It was solution of my problem:
i change row:
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
to:
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
but it was not necessarily to add CalculatorBean to spring-beans.xml
Thanks
org.springframework.web.jsf.el.SpringBeanFacesELResolver is problematic. This article (http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely/) proposes a better solution.
Also, take a look at this answer of mine: How to use Spring services in JSF-managed beans?

Categories