I spent almost 2 days putting these three together to generate a test application. The beauty about this app is it dose not have any xml configuration file except of course the applicationcontext.xml for spring. And in that file also there is just the datasource defined. I thought of putting it down here in order to save somebody stumbling with the same some time.
What Does the app do?
well its just a test application. It shows how to wire everything together just using the annotations. and it also shows the Ajax functionality and the templating functionality of JSF 2.0. and it also inserts some test entity into the Database
Lets get directly dirty with the code
Lets start with the applicationContext.xml file ..
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" 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-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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"> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource" p:driverClassName="${jdbc.driverClass}" p:password="${jdbc.password}" p:url="${jdbc.url}" p:username="${jdbc.username}"> </bean> <bean class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" id="sessionFactory" p:dataSource-ref="dataSource"> <property name="annotatedClasses"> <list> <value>com.test.car.Car</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=${jdbc.showSql} </value> </property> </bean> <bean class="org.springframework.orm.hibernate3.HibernateTransactionManager" id="transactionManager" p:sessionFactory-ref="sessionFactory"/> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory" lazy-init="false" p:dataSource-ref="dataSource"> <property name="persistenceUnitName" value="testsource"/> </bean> <!-- Activates annotation-based bean configuration --> <context:annotation-config/> <!-- needed is for @Configurable --> <context:component-scan base-package="com.test"/> <tx:annotation-driven/> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties"/> </bean> </beans>
As you see all you have done is defined your datasource and wired it with entityManagerFactory which will be used by hibernate. All the connection properties are comming from the file jdbc.properties which is looked up from the classpath so it has to be placed inside the classes directory within WEB-INF. The next thing to do is to add the persistance.xml in META-INF folder which looks like this
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="testsource" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <!-- | The SQL dialect to use for this data source, use MySQL InnoDB as | we only use InnoDB tables for the entity beans. +--> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/> <!-- | Specify the second level query cache for hibernate. +--> <!-- | Enable query caching availability. +--> <!-- <property name="hibernate.cache.use_query_cache" value="true"/> --> </properties> </persistence-unit> </persistence>
As you must have noticed here we only declare the persistence-unit name which is used by spring.
And the last xml file is the faces-config.xml. i know i said just one configuration . here we dont define any beans or navaigation rules here we just have our resource bundle and the reslover for faces beans.
<?xml version="1.0"?> <faces-config 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-facesconfig_2_0.xsd" version="2.0"> <application> <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> <resource-bundle> <base-name>com.test.messages</base-name> <var>msgs</var> </resource-bundle> </application> </faces-config>
so now its all configured. Lets start with the entity class. It looks like this
@Entity @Table(name="user") public class Car implements Serializable{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @NotEmpty @Length(min=1,max=30) private String carName;
next is the DAOimpl class
@Repository public class CarDaoImpl implements CarDao{ private EntityManager entityManagerFactory; @PersistenceContext void setEntityManager(EntityManager entityManager) { this.entityManagerFactory = entityManager; } public void addCar(Car car){ this.entityManagerFactory.persist(car); }
The @Repository annotation is yet another stereotype that was introduced in Spring 2.0 itself. This annotation is used to indicate that a class functions as a repository.
then we have the spring service classes
@Service public class CarServiceImpl implements CarService{ private final CarDao carDao; @Inject CarServiceImpl(CarDao carDao) { this.carDao = carDao; } ...
and finally the backing bean
@ManagedBean("car") @Scope("session") public class CarSession { private Car car; public Car getCar() { return car; } ..
we use annotations for defining managed beans which otherwise would have been declared in ur config file so this significantly reduces your XML, but you can get rid of virtually all of it with JSF 2 through either annotations, as I’m doing for managed beans, or with convention, as is the case for JSF 2’s simplified navigation handling.
so now we have everything in palce .. the only files left are the xhtml files
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" template="/template/masterLayout.xhtml"> <ui:define name="menuLeft"> <!-- <ui:include src="/sections/login/menuLeft.xhtml"/>--> </ui:define> <ui:define name="content"> <ui:include src="/sections/welcome.xhtml"/> </ui:define> </ui:composition>
and the file sections/welcome.xhtml looks like this.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:util="http://java.sun.com/jsf/composite/components/util"> <h:form id="form" prependId="false" > <h:panelGrid> <h:outputText value="#{i18n.prefs_country}"/> <h:selectOneListbox id="company" value="#{car.company}" size="1"> <f:selectItems value="#{facesSupport.carModels}"/> <f:ajax render="model"/> </h:selectOneListbox> <h:outputText value="#{i18n.prefs_region}"/> <h:selectOneListbox id="model" value="#{car.model}" style="width: 180px;" size="1"> <f:selectItems value="#{car.modelOptions}"/> </h:selectOneListbox> </h:panelGrid> <h:commandButton id="loginButton" value="save" action="#{car.saveCar}"/> </h:form></html>
as you see how ajax is used to render the model drop box when ever the company box is changed.
the last thing left is the web.xml file
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/web-application-config.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> <url-pattern>*.faces</url-pattern> </servlet-mapping> <session-config> <session-timeout>500000</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
Thats it .. everything is in place. soon i will zip my test application and upload it so that its easier to go through the code..
Well if there are any questions or suggestions feel free to leave a comment
Finally got some time to create a sample application .. you can download it from here have also included spring security 3.0 into it .. so enjoy ..u can just change from .zip to .war and deploy the application ..but before that dont forget to change the properties file inside /WEB-INF/config add your database connection details there... if there are any questions just write a comment ... and ya .. the source is included inside the war file ... the war file has been tested with tomcat 6 just place it on webapps .. and point ur browser to http://localhost:8080/sample/index.html ..