-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi list!
I'm trying to integrate ZK with the Spring framework, using JPA with Hibernate as the implementation. I followed the smalltalk http://www.zkoss.org/smalltalks/mvc4/, but as far I understood, the demo application use a trick to disable the multiple threads which the ZK framework use to simulate, for example, modal windows. This is, for me, a less than ideal solution, I would like to use all the good features the framework have.
This link: http://coderoony.blogspot.com/2007/07/transaction-management-with-spring.html has some instructions on how to configure everything, and worked well for me. But this post is 2 years old, and I was figuring if there is a better solution already.
Is there anyone with experience with this subject? Any help will be appreciated.
My configuration so far:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="Server_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Servidor Simula</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:br/com/simula/server/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>compression</filter-name>
<filter-class>javawebparts.filter.CompressionFilter</filter-class>
<init-param>
<param-name>compressType</param-name>
<param-value>gzip_first</param-value>
</init-param>
</filter>
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>compression</filter-name>
<url-pattern>/resources/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<!-- The Spring RequestContextLister uses thread bound variables so to
use this Spring freatures requires that we apply <disable-event-thread />
within zk.xml -->
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<description>Used to cleanup when a session is destroyed</description>
<display-name>ZK Session cleaner</display-name>
<listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
</listener>
<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>br.com.simula.server.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<description>
The ZK loader for ZUML pages</description>
<servlet-name>zkLoader</servlet-name>
<servlet-class>
org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
<init-param>
<param-name>update-uri</param-name>
<param-value>/zkau</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<description>
The asynchronous update engine for ZK</description>
<servlet-name>auEngine</servlet-name>
<servlet-class>
org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Spring Web Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zhtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>auEngine</servlet-name>
<url-pattern>/zkau/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>index.zul</welcome-file>
</welcome-file-list>
</web-app>
zk.xml:
<?xml version="1.0" encoding="UTF-8"?>
<zk>
<device-config>
<device-type>ajax</device-type>
<timeout-uri>/timeout.zul</timeout-uri>
<!--
An empty URL can cause the browser to reload the same URL
-->
</device-config>
<listener>
<description>ThreadLocal Variables Synchronizer</description>
<listener-class>org.zkoss.zkplus.util.ThreadLocalListener
</listener-class>
</listener>
<preference>
<name>ThreadLocal</name>
<value>
org.springframework.transaction.support.TransactionSynchronizationManager=resources,synchronizations,currentTransactionName,currentTransactionReadOnly,actualTransactionActive;
org.springframework.orm.hibernate3.SessionFactoryUtils=deferredCloseHolder;
org.springframework.transaction.interceptor.TransactionAspectSupport=transactionInfoHolder;
</value>
</preference>
</zk>
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="serverDatabaseChangeLog" class="liquibase.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:br/com/simula/server/serverDatabaseChangeLog.xml" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="serverDatabaseChangeLog">
<property name="persistenceUnitName" value="serverPU" />
<property name="dataSource" ref="dataSource" />
<property name="jpaProperties">
<props>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statements">50</prop>
</props>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory" />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!--bean id="jpaTemplate"
class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
</bean-->
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="br.com.simula"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
Thanks in advance!
ZK as Front End + Spring and Hibernate Back End + SQL Server and iSeries DB2 Databases
jdbc.properties
# Properties file with JDBC settings. # # Applied by <context:property-placeholder location="jdbc.properties"/> from # various application context XML files (e.g., "spring-*.xml"). # Targeted at system administrators, to avoid touching the context XML files. #------------------------------------------------------------------------------- # Common Settings hibernate.generate_statistics=false hibernate.show_sql=true #------------------------------------------------------------------------------- # Property that determines which Hibernate dialect to use # (only applied with "spring-hibernate-*.xml") hibernate.dialect.sqlserver=org.hibernate.dialect.SQLServerDialect hibernate.dialect.db2as400=org.hibernate.dialect.DB2400Dialect #------------------------------------------------------------------------------- # Property that determines which schema is to use as default hibernate.default_schema.db2as400=GBANCA0008 #------------------------------------------------------------------------------- # IBM Iseries Settings - Only used in Unit Test #jdbc.driverClassName=com.ibm.as400.access.AS400JDBCDriver #jdbc.url=jdbc:as400://SERVER_NAME #jdbc.username=MARCOS #jdbc.password=teste
zk.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- zk.xml Purpose: Description: History: Sun Mar 26 16:29:07 2006, Created by tomyeh Copyright (C) 2006 Potix Corporation. All Rights Reserved. --> <zk> <!-- Optional --> <device-config> <device-type>ajax</device-type> <timeout-uri></timeout-uri> <!-- An empty URL can cause the browser to reload the same URL --> </device-config> <!-- Turn on if you want to ignore the consecutive click events, if it happens too close to the previous one, or the server is still serving the previous click. --> <client-config> <click-filter-delay>390</click-filter-delay> </client-config> <error-page> <exception-type>org.zkoss.zk.ui.UiException</exception-type> <location>/WEB-INF/sys/uiException.zul</location> </error-page> <preference> <name>org.zkoss.zul.Window.defaultActionOnShow </name> <value></value> </preference> <listener> <description>ThreadLocal varaibles synchronizer</description> <listener-class> org.zkoss.zkplus.util.ThreadLocalListener </listener-class> </listener> <preference> <name>ThreadLocal</name> <value> org.springframework.web.context.request.RequestContextHolder=requestAttributesHolder,inheritableRequestAttributesHolder; org.springframework.transaction.support.TransactionSynchronizationManager=resources,synchronizations,currentTransactionName,currentTransactionReadOnly,actualTransactionActive; org.springframework.orm.hibernate3.SessionFactoryUtils=deferredCloseHolder; org.springframework.transaction.interceptor.TransactionAspectSupport=transactionInfoHolder; </value> </preference> </zk>
spring-as400-appname.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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" 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"> <!-- ========================= RESOURCE DEFINITIONS ========================= --> <!-- Configurer that replaces ${...} placeholders with values from a properties file --> <!-- (in this case, JDBC-related settings for the dataSource definition below) --> <!-- <context:property-placeholder location="/WEB-INF/classes/jdbc.properties"/> --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- Hibernate SessionFactory --> <bean id="sessionFactoryAS400" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" p:dataSource-ref="dataSourceAS400"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect.db2as400}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop> <prop key="hibernate.default_schema">${hibernate.default_schema.db2as400}</prop> </props> </property> <property name="annotatedClasses"> <list> <value>com.bci.bcicaixa.model.Gbpcx</value> </list> </property> <property name="eventListeners"> <map> <entry key="merge"> <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> </entry> </map> </property> </bean> <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> <bean id="transactionManagerAS400" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactoryAS400"/> <!-- Parâmetros de Caixa --> <bean id="gbpcxDao" class="com.bci.bcicaixa.dao.GenericDaoImpl"> <constructor-arg index="0" value="com.bci.bcicaixa.model.Gbpcx" /> <constructor-arg index="1" ref="sessionFactoryAS400" /> </bean> <bean id="gbpcxService" class="com.bci.bcicaixa.service.GenericServiceImpl"> <constructor-arg ref="gbpcxDao" /> </bean> </beans>
spring-sqlserver-appname.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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" 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"> <!-- ========================= RESOURCE DEFINITIONS ========================= --> <!-- Configurer that replaces ${...} placeholders with values from a properties file --> <!-- (in this case, JDBC-related settings for the dataSource definition below) --> <!-- <context:property-placeholder location="/WEB-INF/classes/jdbc.properties"/> --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- Hibernate SessionFactory --> <bean id="sessionFactorySQLSERVER" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" p:dataSource-ref="dataSourceSQLSERVER"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect.sqlserver}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop> </props> </property> <property name="annotatedClasses"> <list> <value>com.bci.bcicaixa.model.Sistema</value> </list> </property> <property name="eventListeners"> <map> <entry key="merge"> <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> </entry> </map> </property> </bean> <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> <bean id="transactionManagerSQLSERVER" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactorySQLSERVER"/> <!-- Sistema --> <bean id="sistemaDao" class="com.bci.bcicaixa.dao.GenericDaoImpl"> <constructor-arg index="0" value="com.bci.bcicaixa.model.Sistema" /> <constructor-arg index="1" ref="sessionFactorySQLSERVER" /> </bean> <bean id="sistemaService" class="com.bci.bcicaixa.service.GenericServiceImpl"> <constructor-arg ref="sistemaDao" /> </bean> </beans>
spring-jndi-appname.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:jee="http://www.springframework.org/schema/jee" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-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/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- ========================= RESOURCE DEFINITIONS ========================= --> <!-- JNDI DataSource for J2EE environments --> <jee:jndi-lookup id="dataSourceSQLSERVER" jndi-name="java:comp/env/jdbc/microsoft/bcicaixa" /> <jee:jndi-lookup id="dataSourceAS400" jndi-name="java:comp/env/jdbc/ibm/bcicaixa" /> <!-- Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @Resource. --> <context:annotation-config /> <!-- Instruct Spring to perform declarative transaction management automatically on annotated classes. --> <tx:annotation-driven transaction-manager="transactionManagerSQLSERVER" /> <tx:annotation-driven transaction-manager="transactionManagerAS400" /> </beans>
spring-view-appname.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- - Application context definition for view layer. --> <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" 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/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"> <!-- ========================= VIEW OBJECT DEFINITIONS ========================= --> <!-- - bcicaixa's view object definitions - All Service is injected using @Autowired --> <bean id="loginForm" class="com.bci.bcicaixa.web.LoginForm" scope="prototype" /> </beans>
GenericDao.java
package com.bci.bcicaixa.dao; import java.io.Serializable; import java.util.Collection; import java.util.List; import org.springframework.dao.DataAccessException; /** * Generic DAO (Data Access Object) with common methods to CRUD POJOs. * * <p>Extend this interface if you want typesafe (no casting necessary) DAO's for your * domain objects. * * @author marcos.sousa * @param <T> a type variable * @param <PK> the primary key for that type */ public interface GenericDao<T, PK extends Serializable> { /** * Return the persistent instance of the given entity class with the given identifier, * or null if there is no such persistent instance. * * @param id an identifier * @return a persistent instance or null */ public T get(PK id) throws DataAccessException; /** * Return the persistent instance of the given entity class with the given identifier, * assuming that the instance exists. * * @param id a valid identifier of an existing persistent instance of the class * @return the persistent instance */ public T load(PK id) throws DataAccessException; /** * Return all persistent instances. * * @return The list of persistent instances */ public Collection<T> getAll() throws DataAccessException; /** * Copy the state of the given object onto the persistent object with the same * identifier. * * @param object a detached instance with state to be copied * @return an updated persistent instance */ public T merge(T object) throws DataAccessException; /** * Persist the given transient instance, first assigning a generated identifier. * * @param object a transient instance of a persistent class * @return the generated identifier */ public PK save(T object) throws DataAccessException; /** * Persist the given transient instance, first assigning a generated identifier. * * @param objects an list of transients instance of a persistent class */ public void saveAll(List<T> objects) throws DataAccessException; /** * Update the persistent instance with the identifier of the given detached * instance. * * @param object a detached instance containing updated state */ public void update(T object) throws DataAccessException; /** * Remove a persistent instance from the datastore. * * @param object the instance to be removed */ public void delete(T object) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) */ public Collection<T> findByExample(final T exampleEntity) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @param firstResult the index of the first result object to be retrieved (numbered from 0) * @param maxResults the maximum number of result objects to retrieve (or <=0 for no limit) * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) * @see org.hibernate.Criteria#setFirstResult(int) * @see org.hibernate.Criteria#setMaxResults(int) */ public Collection<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @return a single instance that matches the query, or null if the query returns no results. * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) */ public T getByExample(final T exampleEntity) throws DataAccessException; public Integer countByExample(final T exampleEntity) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @param firstResult the index of the first result object to be retrieved (numbered from 0) * @param maxResults the maximum number of result objects to retrieve (or <=0 for no limit) * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz, final int firstResult, final int maxResults) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @return a single instance that matches the query, or null if the query returns no results. * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public T getBySQLQuery(String sqlQueryString) throws DataAccessException; public Integer countBySQLQuery(String sqlQueryString) throws DataAccessException; }
GenericDaoImpl.java
package com.bci.bcicaixa.dao; import java.io.Serializable; import java.util.Collection; import java.util.List; import org.hibernate.Criteria; import org.hibernate.SQLQuery; import org.hibernate.SessionFactory; import org.hibernate.criterion.Example; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Projections; import org.springframework.dao.DataAccessException; import org.springframework.util.Assert; /** * This class serves as the Base class for all other DAOs - namely to hold * common CRUD methods that they might all use. You should only need to extend * this class when your require custom CRUD logic. * * <p>To register this class in your Spring context file, use the following XML. * <pre> * <bean id="xxxDao" class="com.bci.bcicaixa.dao.GenericDaoImpl"> * <constructor-arg value="com.bci.bcicaixa.model.Xxx"/> * </bean> * </pre> * * @author marcos.sousa * @param <T> a type variable * @param <PK> the primary key for that type */ @SuppressWarnings("unchecked") public class GenericDaoImpl<T, PK extends Serializable> implements GenericDao<T, PK> { private SessionFactory sessionFactory; private Class<T> persistentClass; /** * Constructor that takes in a class to see which type of entity to persist * * @param persistentClass the class type you'd like to persist */ public GenericDaoImpl(Class<T> persistentClass, SessionFactory sessionFactory) { this.persistentClass = persistentClass; this.sessionFactory = sessionFactory; } /** * {@inheritDoc} */ public T get(PK id) throws DataAccessException { return (T) sessionFactory.getCurrentSession().get(this.persistentClass, id); } /** * {@inheritDoc} */ public T load(PK id) throws DataAccessException { return (T) sessionFactory.getCurrentSession().load(this.persistentClass, id); } /** * {@inheritDoc} */ public Collection<T> getAll() throws DataAccessException { return sessionFactory.getCurrentSession().createCriteria(this.persistentClass).list(); } /** * {@inheritDoc} */ public T merge(T object) throws DataAccessException { // Note: Hibernate3's merge operation does not reassociate the object // with the current Hibernate Session. Instead, it will always copy the // state over to a registered representation of the entity. In case of a // new entity, it will register a copy as well, but will not update the // id of the passed-in object. To still update the ids of the original // objects too, we need to register Spring's // IdTransferringMergeEventListener on our SessionFactory. return (T) sessionFactory.getCurrentSession().merge(object); } /** * {@inheritDoc} */ public PK save(T object) throws DataAccessException { return (PK) sessionFactory.getCurrentSession().save(object); } /** * {@inheritDoc} */ public void saveAll(List<T> objects) { for (T t : objects) { sessionFactory.getCurrentSession().save(t); } } /** * {@inheritDoc} */ public void update(T object) throws DataAccessException { sessionFactory.getCurrentSession().update(object); } /** * {@inheritDoc} */ public void delete(T object) throws DataAccessException { sessionFactory.getCurrentSession().delete(object); } /** * {@inheritDoc} */ public Collection<T> findByExample(final T exampleEntity) throws DataAccessException { Assert.notNull(exampleEntity, "Example entity must not be null"); Criteria criteria = sessionFactory.getCurrentSession().createCriteria(this.persistentClass); return criteria.add(Example.create(exampleEntity).ignoreCase().enableLike(MatchMode.ANYWHERE)).list(); } /** * {@inheritDoc} */ public Collection<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults) throws DataAccessException { Assert.notNull(exampleEntity, "Example entity must not be null"); Criteria criteria = sessionFactory.getCurrentSession().createCriteria(this.persistentClass); if (firstResult >= 0) { criteria.setFirstResult(firstResult); } if (maxResults > 0) { criteria.setMaxResults(maxResults); } return criteria.add(Example.create(exampleEntity).ignoreCase().enableLike(MatchMode.ANYWHERE)).list(); } /** * {@inheritDoc} */ public T getByExample(final T exampleEntity) throws DataAccessException { Assert.notNull(exampleEntity, "Example entity must not be null"); Criteria criteria = sessionFactory.getCurrentSession().createCriteria(this.persistentClass); criteria.setMaxResults(1); return (T)criteria.add(Example.create(exampleEntity).ignoreCase().enableLike(MatchMode.ANYWHERE)).uniqueResult(); } /** * {@inheritDoc} */ public Integer countByExample(final T exampleEntity) throws DataAccessException { Assert.notNull(exampleEntity, "Example entity must not be null"); Criteria criteria = sessionFactory.getCurrentSession().createCriteria(this.persistentClass); criteria.setProjection(Projections.rowCount()); criteria.add(Example.create(exampleEntity).ignoreCase().enableLike(MatchMode.ANYWHERE)); return (Integer)criteria.uniqueResult(); } /** * {@inheritDoc} */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz) throws DataAccessException { SQLQuery sqlQuery = sessionFactory.getCurrentSession().createSQLQuery(sqlQueryString); sqlQuery.addEntity(clazz); return sqlQuery.list(); } /** * {@inheritDoc} */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz, final int firstResult, final int maxResults) throws DataAccessException { SQLQuery sqlQuery = sessionFactory.getCurrentSession().createSQLQuery(sqlQueryString); sqlQuery.addEntity(clazz); if (firstResult >= 0) { sqlQuery.setFirstResult(firstResult); } if (maxResults > 0) { sqlQuery.setMaxResults(maxResults); } return sqlQuery.list(); } /** * {@inheritDoc} */ public T getBySQLQuery(String sqlQueryString) throws DataAccessException { SQLQuery sqlQuery = sessionFactory.getCurrentSession().createSQLQuery(sqlQueryString); sqlQuery.setMaxResults(1); return (T)sqlQuery.uniqueResult(); } /** * {@inheritDoc} */ public Integer countBySQLQuery(String sqlQueryString) throws DataAccessException { SQLQuery sqlQuery = sessionFactory.getCurrentSession().createSQLQuery(sqlQueryString); sqlQuery.setMaxResults(1); return (Integer)sqlQuery.uniqueResult(); } }
GenericService.java
package com.bci.bcicaixa.service; import java.io.Serializable; import java.util.Collection; import java.util.List; import org.springframework.dao.DataAccessException; /** * Generic Service that talks to GenericDao to CRUD POJOs. * * <p>Extend this interface if you want typesafe (no casting necessary) managers * for your domain objects. * * @author marcos.sousa * @param <T> a type variable * @param <PK> the primary key for that type */ public interface GenericService<T, PK extends Serializable> { /** * Return the persistent instance of the given entity class with the given identifier, * or null if there is no such persistent instance. * * @param id an identifier * @return a persistent instance or null */ public T get(PK id) throws DataAccessException; /** * Return the persistent instance of the given entity class with the given identifier, * assuming that the instance exists. * * @param id a valid identifier of an existing persistent instance of the class * @return the persistent instance */ public T load(PK id) throws DataAccessException; /** * Return all persistent instances. * * @return The list of persistent instances */ public Collection<T> getAll() throws DataAccessException; /** * Copy the state of the given object onto the persistent object with the same * identifier. * * @param object a detached instance with state to be copied * @return an updated persistent instance */ public T merge(T object) throws DataAccessException; /** * Persist the given transient instance, first assigning a generated identifier. * * @param object a transient instance of a persistent class * @return the generated identifier */ public PK save(T object) throws DataAccessException; /** * Persist the given transient instance, first assigning a generated identifier. * * @param objects an list of transients instance of a persistent class */ public void saveAll(List<T> objects) throws DataAccessException; /** * Update the persistent instance with the identifier of the given detached * instance. * * @param object a detached instance containing updated state */ public void update(T object) throws DataAccessException; /** * Remove a persistent instance from the datastore. * * @param object the instance to be removed */ public void delete(T object) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) */ public Collection<T> findByExample(final T exampleEntity) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @param firstResult the index of the first result object to be retrieved (numbered from 0) * @param maxResults the maximum number of result objects to retrieve (or <=0 for no limit) * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) * @see org.hibernate.Criteria#setFirstResult(int) * @see org.hibernate.Criteria#setMaxResults(int) */ public Collection<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults) throws DataAccessException; /** * Execute a query based on a given example entity object. * * @param exampleEntity an instance of the desired entity, serving as example for "query-by-example" * @return a single instance that matches the query, or null if the query returns no results. * @throws org.springframework.dao.DataAccessException in case of Hibernate errors * @see org.hibernate.criterion.Example#create(Object) */ public T getByExample(final T exampleEntity) throws DataAccessException; public Integer countByExample(final T exampleEntity) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @param firstResult the index of the first result object to be retrieved (numbered from 0) * @param maxResults the maximum number of result objects to retrieve (or <=0 for no limit) * @return a {@link List} containing 0 or more persistent instances * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz, final int firstResult, final int maxResults) throws DataAccessException; /** * Execute a query based on the given SQL query string. * * @param sqlQueryString a SQL query * @return a single instance that matches the query, or null if the query returns no results. * @throws org.springframework.dao.DataAccessException in case of Hibernate errors */ public T getBySQLQuery(String sqlQueryString) throws DataAccessException; public Integer countBySQLQuery(String sqlQueryString) throws DataAccessException; }
GenericServiceImpl.java
package com.bci.bcicaixa.service; import java.io.Serializable; import java.util.Collection; import java.util.List; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.bci.bcicaixa.dao.GenericDao; import com.bci.bcicaixa.util.Constantes; /** * This class serves as the Base class for all other Services - namely to hold * common CRUD methods that they might all use. You should only need to extend * this class when your require custom CRUD logic. * * <p>To register this class in your Spring context file, use the following XML. * <pre> * <bean id="xxxService" class="com.bci.bcicaixa.service.GenericServiceImpl"> * <constructor-arg ref="xxxDao"/> * </bean> * </pre> * * @author marcos.sousa * @param <T> a type variable * @param <PK> the primary key for that type */ @Repository @Transactional public class GenericServiceImpl<T, PK extends Serializable> implements GenericService<T, PK> { /** * GenericDao instance, set by constructor of this class */ private GenericDao<T, PK> genericDao; /** * Public constructor for creating a new GenericServiceImpl. * * @param genericDao the GenericDao to use for persistence */ public GenericServiceImpl(GenericDao<T, PK> genericDao) { this.genericDao = genericDao; } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public T get(PK id) throws DataAccessException { return this.genericDao.get(id); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public T load(PK id) throws DataAccessException { return this.genericDao.load(id); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Collection<T> getAll() throws DataAccessException { return this.genericDao.getAll(); } /** * {@inheritDoc} */ @Transactional(timeout = Constantes.TRANSACTION_TIMEOUT) public T merge(T object) throws DataAccessException { return this.genericDao.merge(object); } /** * {@inheritDoc} */ @Transactional(timeout = Constantes.TRANSACTION_TIMEOUT) public PK save(T object) throws DataAccessException { return this.genericDao.save(object); } /** * {@inheritDoc} */ @Transactional(timeout = Constantes.TRANSACTION_TIMEOUT) public void saveAll(List<T> objects) throws DataAccessException { this.genericDao.saveAll(objects); } /** * {@inheritDoc} */ @Transactional(timeout = Constantes.TRANSACTION_TIMEOUT) public void update(T object) throws DataAccessException { this.genericDao.update(object); } /** * {@inheritDoc} */ @Transactional(timeout = Constantes.TRANSACTION_TIMEOUT) public void delete(T object) throws DataAccessException { this.genericDao.delete(object); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Collection<T> findByExample(final T exampleEntity) throws DataAccessException { return this.genericDao.findByExample(exampleEntity); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Collection<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults) throws DataAccessException { return this.genericDao.findByExample(exampleEntity, firstResult, maxResults); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public T getByExample(final T exampleEntity) throws DataAccessException { return this.genericDao.getByExample(exampleEntity); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Integer countByExample(final T exampleEntity) throws DataAccessException { return this.genericDao.countByExample(exampleEntity); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz) throws DataAccessException { return this.genericDao.findBySQLQuery(sqlQueryString, clazz); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Collection<T> findBySQLQuery(String sqlQueryString, Class clazz, final int firstResult, final int maxResults) throws DataAccessException { return this.genericDao.findBySQLQuery(sqlQueryString, clazz, firstResult, maxResults); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public T getBySQLQuery(String sqlQueryString) throws DataAccessException { return this.genericDao.getBySQLQuery(sqlQueryString); } /** * {@inheritDoc} */ @Transactional(readOnly = true, timeout = Constantes.QUERY_TIMEOUT) public Integer countBySQLQuery(String sqlQueryString) throws DataAccessException { return this.genericDao.countBySQLQuery(sqlQueryString); } }
LoginForm.java
package com.bci.bcicaixa.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.zkoss.zk.ui.event.Event; import org.zkoss.zul.Label; import org.zkoss.zul.Textbox; import com.bci.bcicaixa.model.Gbpcx; /** * Formulário Controller que é usado para suportar o Login do Sistema. É deste * Controller que é feito o auto-login (remember-me). * * @author marcos.sousa */ @SuppressWarnings("unchecked") public class LoginForm extends SimpleWindow { @Autowired @Qualifier("gbpcxService") private GenericService gbpcxService; private Label estacaoAs400; private Textbox user; private Textbox password; public LoginForm() { } public void onClick$entrar(Event event) { try { Gbpcx gbpcx = (Gbpcx)gbpcxService.getGbpuser(user.getValue()); } catch (Exception e) { log.error("Erro ao efectuar login.", e); showError(e.getMessage()); } } public void onOK$loginForm(Event event) { onClick$entrar(event); } }
index.zul
<?page id="indexPage" title="BCI - O MEU BANCO" contentType="text/html;charset=UTF-8"?> <?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?> <?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?> <?evaluator name="mvel"?> <zk> <borderlayout> <north size="35%" border="none"></north> <west size="40%" border="none"></west> <center border="none"> <window id="loginForm" width="100%" border="normal" apply="${loginForm}"> <caption image="/img/logo24x24.png" label="O MEU BANCO" /> <grid> <rows> <row>Estação: <label id="estacaoAs400" /></row> <row>Utilizador: <textbox id="user" /></row> <row>Password: <textbox id="password" type="password" /></row> <row spans="2" align="center"><button id="entrar" label="Entrar" mold="os" /></row> </rows> </grid> </window> </center> <east size="40%" border="none"></east> <south size="35%" border="none"></south> </borderlayout> </zk>
context.xml
<?xml version="1.0" encoding="UTF-8"?> <Context crossContext="true" reloadable="true"> <!-- Define a database connection pool for Microsoft SQL Server --> <!-- NOTE: make sure that a copy of sqljdbc.jar is in the TOMCAT common/lib directory --> <Resource name="jdbc/microsoft/bcicaixa" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://SEVER:1433" defaultCatalog="bcicaixa" username="xx" password="xxxx" maxActive="30" maxIdle="10" maxWait="5000" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" validationQuery="Select * From bcicaixa..sistema" /> <Resource name="jdbc/ibm/bcicaixa" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" driverClassName="com.ibm.as400.access.AS400JDBCDriver" url="jdbc:as400://SERVER" defaultCatalog="GBANCA0008" username="MARCOS" password="teste" maxActive="30" maxIdle="10" maxWait="5000" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true" validationQuery="Select * from GBANCA0008.hoje" /> </Context>
Hope this help you
If you want know more about real application, please check my blog www.marcos.co.nr
I will start to release one post at least by week.
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"> <display-name>bcicaixa</display-name> <listener> <description> Used to cleanup when a session is destroyed </description> <display-name>ZK Session Cleaner</display-name> <listener-class> org.zkoss.zk.ui.http.HttpSessionListener </listener-class> </listener> <servlet> <description>ZK loader for ZUML pages</description> <servlet-name>zkLoader</servlet-name> <servlet-class> org.zkoss.zk.ui.http.DHtmlLayoutServlet </servlet-class> <init-param> <param-name>update-uri</param-name> <param-value>/zkau</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>zkLoader</servlet-name> <url-pattern>*.zul</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>zkLoader</servlet-name> <url-pattern>*.zhtml</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>zkLoader</servlet-name> <url-pattern>*.svg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>zkLoader</servlet-name> <url-pattern>*.xml2html</url-pattern> </servlet-mapping> <servlet> <description>The asynchronous update engine for ZK</description> <servlet-name>auEngine</servlet-name> <servlet-class> org.zkoss.zk.au.http.DHtmlUpdateServlet </servlet-class> </servlet> <servlet> <description> The servlet loads the DSP pages.</description> <servlet-name>dspLoader</servlet-name> <servlet-class> org.zkoss.web.servlet.dsp.InterpreterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>auEngine</servlet-name> <url-pattern>/zkau/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>dspLoader</servlet-name> <url-pattern>*.dsp</url-pattern> </servlet-mapping> <!-- INI SPRING --> <!-- - Location of the XML file that defines the root application context. - Applied by ContextLoaderServlet. --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring-*.xml </param-value> </context-param> <!-- - Loads the root application context of this web app at startup, - by default from "/WEB-INF/applicationContext.xml". - Note that you need to fall back to Spring's ContextLoaderServlet for - J2EE servers that do not follow the Servlet 2.4 initialization order. - - Use WebApplicationContextUtils.getWebApplicationContext(servletContext) - to access it anywhere in the web application, outside of the framework. - - The root context is the parent of all servlet-specific contexts. - This means that its beans are automatically available in these child contexts, - both for getBean(name) calls and (external) bean references. --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <!-- END SPRING --> <session-config> <session-timeout>10</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> <welcome-file>index.zul</welcome-file> </welcome-file-list> <mime-mapping> <extension>doc</extension> <mime-type>application/vnd.ms-word</mime-type> </mime-mapping> <mime-mapping> <extension>gif</extension> <mime-type>image/gif</mime-type> </mime-mapping> <mime-mapping> <extension>htm</extension> <mime-type>text/html</mime-type> </mime-mapping> <mime-mapping> <extension>html</extension> <mime-type>text/html</mime-type> </mime-mapping> <mime-mapping> <extension>jad</extension> <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type> </mime-mapping> <mime-mapping> <extension>jnlp</extension> <mime-type>application/x-java-jnlp-file</mime-type> </mime-mapping> <mime-mapping> <extension>jpeg</extension> <mime-type>image/jpeg</mime-type> </mime-mapping> <mime-mapping> <extension>jpg</extension> <mime-type>image/jpeg</mime-type> </mime-mapping> <mime-mapping> <extension>js</extension> <mime-type>application/x-javascript</mime-type> </mime-mapping> <mime-mapping> <extension>pdf</extension> <mime-type>application/pdf</mime-type> </mime-mapping> <mime-mapping> <extension>png</extension> <mime-type>image/png</mime-type> </mime-mapping> <mime-mapping> <extension>rar</extension> <mime-type>application/x-rar-compressed</mime-type> </mime-mapping> <mime-mapping> <extension>txt</extension> <mime-type>text/plain</mime-type> </mime-mapping> <mime-mapping> <extension>xls</extension> <mime-type>application/vnd.ms-excel</mime-type> </mime-mapping> <mime-mapping> <extension>xml</extension> <mime-type>text/xml</mime-type> </mime-mapping> <mime-mapping> <extension>xul</extension> <mime-type>application/vnd.mozilla.xul-xml</mime-type> </mime-mapping> <mime-mapping> <extension>zhtml</extension> <mime-type>text/html</mime-type> </mime-mapping> <mime-mapping> <extension>zip</extension> <mime-type>application/x-zip</mime-type> </mime-mapping> <mime-mapping> <extension>zul</extension> <mime-type>text/html</mime-type> </mime-mapping> </web-app>
Yeaah, that's absolut great. Thanks you in all names for the code, Marcos.
Stephan
Asked: 2009-08-05 13:57:29 +0800
Seen: 1,809 times
Last updated: Aug 09 '09