for use with Red Hat JBoss Enterprise Application Platform
Legal Notice
Abstract
- 1. Spring Future Support
- 2. Introduction to Red Hat JBoss Web Framework Kit
- 3. Overview of Spring with Red Hat JBoss Enterprise Application Platform
- 4. Installing Spring
- 5. Configuring Spring
- 6. Spring in Action
- 7. Migrating Spring Applications
- A. Revision History
Chapter 1. Spring Future Support
Chapter 2. Introduction to Red Hat JBoss Web Framework Kit
2.1. About Red Hat JBoss Web Framework Kit
2.2. About the JBoss Web Framework Kit Tiers
- Tier 1 - Included Components
- These are components that are based wholly or partly on open source technologies that support broad collaboration and where Red Hat maintains a leadership role; as such Red Hat is able to support these components and provide upgrades and fixes under our standard support terms and conditions.
- Tier 2 - Tested Frameworks
- These are third-party frameworks where Red Hat does not have sufficient influence and does not provide upgrades and fixes under our standard support terms and conditions. Commercially reasonable support is provided by Red Hat Global Support Services for these frameworks.
- Tier 3 - Frameworks in Tested Examples
- These are third-party frameworks where Red Hat does not have sufficient influence and does not provide upgrades and fixes under our standard support terms and conditions. Red Hat supports the examples these frameworks are used in and the generic use cases that these examples intend to demonstrate.
- Tier 4 - Confirmed Frameworks
- These are third-party frameworks that do not receive any support from Red Hat, but Red Hat verifies that the frameworks run successfully on Red Hat JBoss Enterprise Application Platform. Frameworks and versions not listed here have not been explicitly tested and certified, and thus may be subject to support limitations.
2.3. About the JBoss Web Framework Kit Distribution
- The component frameworks are available from the Red Hat Customer Portal. They are distributed in two alternative formats: a binary for each framework or together as one Maven repository. In addition, the source code for each framework is provided for inspection.
- The third party frameworks are not distributed by Red Hat and each must be obtained from its own source.
.zip file available to download from the Red Hat Customer Portal or from http://www.jboss.org/developer-materials/ on the JBoss Developer Framework website.
- TicketMonster is a moderately complex application demonstrating a number of the JBoss Web Framework Kit frameworks working together.
- Quickstarts and Maven archeypes illustrate subsets of the JBoss Web Framework Kit frameworks used to create simple applications.
- RichFaces, Snowdrop and Seam demonstrations showcase the power of each framework in web application development.
Chapter 3. Overview of Spring with Red Hat JBoss Enterprise Application Platform
3.1. About Spring Framework
3.2. About Spring and Red Hat JBoss Enterprise Application Platform
Table 3.1. Use cases
| Category | Use case | How does this involve JBoss Enterprise Application Platform |
|---|---|---|
| Persistence | Spring/Hibernate integration | The application uses a Spring-configured Hibernate SessionFactory, using JTA transaction management and JTA-bound sessions. The Hibernate library is the one provided by JBoss Enterprise Application Platform. |
| Spring/JPA integration | The Persistence Unit is deployed by JBoss Enterprise Application Platform and retrieved from JNDI to be injected into Spring beans. PersistenceContext is shared with surrounding EJBs (if any). | |
| Testing | Unit-testing components that have managed infrastructure dependencies | The DataSource and EntityManager are managed by JBoss Enterprise Application Platform and acquired from JNDI by Spring when the application is running. In the case of JBoss Enterprise Application Platform, developers can test their code in isolation using Spring-specific replacements that simulate the JBoss Enterprise Application Platform environment. |
| Business Logic | Spring-based service beans | The business services are Spring-managed and wrapped into transactions managed by Spring's interceptors. The TransactionManager in use is the JTATransactionManager using Transactions provided in JBoss Enterprise Application Platform. |
| EJBs injected with Spring Beans | The application uses JBoss-deployed EJBs which are injected with Spring beans acquired from an application context bootstrapped by the Spring Deployer. Transactions are managed by EJBs. | |
| User Interface | JSF/RichFaces and Spring integration | The application uses JSF support and RichFaces components provided by JBoss Enterprise Application Platform. The business services and UI-backing instances are Spring beans. |
| Spring MVC and EJB integration | The application uses Spring MVC and the business logic is implemented using JBoss-deployed EJBs, which are injected into the Spring controllers. | |
| Conversation-oriented web application | The application uses Spring Web Flow for defining a conversational process for creating a reservation. | |
| JMS/JCA integration | JMS/Spring integration using JCA | The application uses Spring-configured message listeners for processing JMS messages from destinations managed by JBoss Enterprise Application Platform and Spring /JCA integration for receiving messages. |
| JMX | Spring beans are exposed as JMX beans | The JBoss Enterprise Application Platform MBean Server is used for registering the Spring-exported JMX beans. Consequently, the Spring beans can be managed from a management console. |
| Web Services | JAX-WS defined web-services are injected with Spring beans | The application uses JBoss Enterprise Application Platforms' support for JAX-WS through JBoss WS, but also Spring to define the underlying business logic, which is injected into the JBoss WS-deployed services. |
| A Spring Web Services-based variant of the JAX-WS example | The application implements a web service based on Spring Web Services. | |
| Security | Application-server pre-authentication | The application uses Spring Security for authorizing access to resources. Authentication is provided by the application server. |
Chapter 4. Installing Spring
4.1. Prerequisites
- Maven 3.0.4
- Red Hat JBoss Developer Studio 8
- Red Hat JBoss Enterprise Application Platform 6
Note
- 2.5.6.SEC03
- 3.0.7.RELEASE
- 3.1.4.RELEASE
- 3.2.13.RELEASE
- 4.0.9.RELEASE
- 4.1.4.RELEASE
Warning
- Spring 2.5 is deprecated from the release of JBoss Web Framework Kit 2.4.0. This means that Spring 2.5 will continue to be tested and supported in JBoss Web Framework Kit 2.x but it will not be tested or supported in JBoss Web Framework Kit 3 and later. Note that subsequent Spring 2 releases will not be tested or supported in JBoss Web Framework Kit.
- Spring 3.0.x and 3.1.x are deprecated from the release of JBoss Web Framework Kit 2.5.0. This means that Spring 3.0.x and 3.1.x will continue to be tested and supported in JBoss Web Framework Kit 2.x but they will not be tested or supported in JBoss Web Framework Kit 3 and later. Spring 3.2.x and later are not deprecated and continue to be tested and supported in JBoss Web Framework Kit.
- Support for Spring 4 as a tested framework is limited to the features supported by Red Hat JBoss Enterprise Application Platform. Specifically, support is not provided for the new features in Spring 4 related to Java SE 8 and Java EE 7.
- Installing the framework libraries as shared libraries on the platform
- Packaging the framework libraries together with the application (in application archives)
4.2. Spring as Shared Libraries
EAP_HOME/modules/system/add-ons directory of the application server. A JBoss Enterprise Application Platform module is identified or referenced by its identifier and slot. This section, uses a module with the org.springframework.spring identifier, and the main slot. This is the default slot: if a slot name is unspecified, JBoss Enterprise Application Platform assumes a slot name of 'main' for identifying the module.
Procedure 4.1. Installing Spring as a Shared Library
- Create
EAP_HOME/modules/system/add-ons/org/springframework/spring/maindirectory.This path consists of a main directory (org/springframework/spring) which reflects the module identifier and a subdirectory (main) which reflects the slot name. - Copy the Spring JARs, to be shared, in the
EAP_HOME/modules/system/add-ons/org/springframework/spring/maindirectory. - Create a
module.xmldescriptor, which includes references to the Spring JARs and application server dependencies to the module. Each JAR copied to the module folder must have a distinct<resource-root>entry in the module descriptor.Example 4.1. Example module.xml file
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="org.springframework.spring" slot="main"> <resources> <resource-root path="aopalliance.jar"/> <resource-root path="aspectjrt.jar"/> <resource-root path="aspectjweaver.jar"/> <resource-root path="spring-aop.jar"/> <resource-root path="spring-beans.jar"/> <resource-root path="spring-context.jar"/> <resource-root path="spring-context-support.jar"/> <resource-root path="spring-core.jar"/> <resource-root path="spring-expression.jar"/> <resource-root path="spring-web.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> ... </dependencies> </module>
The module name and slot must match the directory structure of the module.
<lib/> element of the WAR or EAR tasks. In Maven builds, set the scope to provided.
4.3. Referencing the Spring Module
/META-INF/jboss-deployment-structure.xml or /WEB-INF/jboss-deployment-structure.xml descriptors as follows:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"> <deployment> <dependencies> <module name="org.springframework.spring" slot="<slot-name>"> <imports> <include path="META-INF**"/> <include path="org**"/> </imports> </module> </dependencies> </deployment> </jboss-deployment-structure>
<imports> element in the descriptor is critical for the proper functioning of the Spring custom namespace capabilities. For applications that use custom namespaces and require a shared Spring module, you must use the JBoss Enterprise Application Platform deployment structure descriptors with the <imports> element. Applications can also reference the module through manifest by adding the following to the META-INF/MANIFEST.MF file:
Dependencies: org.springframework.spring:<slot-name>
META-INF/MANIFEST.MF file does not allow the usage of custom Spring namespaces.
4.4. Benefits and Drawbacks of Spring as Shared Library
Advantages
- Reduces the size of the packaged applications(EARs, WARs, RARs)
- Reduces the number of times classloaders load Spring classes
- Provides a simple path to upgrade to a different version of Spring (a single place to do the replacement)
Disadvantages
- Flexibility considerations:The Spring module gets integrated with JBoss Enterprise Application Platform module system, and the dependencies of Spring modules are required to be reflected in the dependency system of the applications using it. As a result, the application becomes less isolated from rest of the application server. This is not necessarily a disadvantage but an item to consider when sharing Spring.
- Build Requirements:All applications deployed on the server must be built in a way that does not package Spring.
- Operational Issues:Installing the shared Spring libraries becomes part of the application server setup. The packaged applications do not contain the Spring libraries, and do not run on a server that does not contain the shared Spring libraries.
4.5. Spring in Application Archives
- In WAR
- In the
WEB-INF/libdirectory. - In EAR
- In the
/libfolder of the archive, or another folder specified in theMETA-INF/application.xmldescriptor.In EARs that contain WARs, package Spring either in the shared library directory of the EAR, or in theWEB-INF/libdirectory of individual WARs that use Spring. Unless the WARs use different versions of Spring (not a common case), Red Hat recommends you to package Spring as a shared library of the EARs. - In RAR
- In the root directory of the archive.
Warning
TheSpringContextResourceAdaptorpresent in Spring 3.0.7.RELEASE and Spring 2.5.6.SEC03 violates section 5.3.1 of the JCA 1.5 specification. As a consequence, RARs containing packaged Spring files from these versions cause deployment errors on Red Hat JBoss Enterprise Application Platform.To work around this issue, disable archive validation in the JCA subsystem by adding the following code to the server configuration: <subsystem xmlns="urn:jboss:domain:jca:1.1"> <archive-validation enabled="false" /> </subsystem>
4.6. Benefits and Drawbacks of Spring in Application Archives
Advantages
- Every application deployed on the server can use a different version of Spring
- Build scripts are simpler
- Packaged applications can be deployed on different server instances, that is, the target server is not required to be prepared for a specific deployment
Disadvantages
- Size of the application archive increases
- Memory usage is not efficient as classes common to all applications are loaded multiple times
4.7. Using Spring With JBoss Spring Deployer
org.springframework.spring module using the dedicated snowdrop slot. Refer the Snowdrop User Guide for more information on the Spring Deployer.
Chapter 5. Configuring Spring
5.1. Overview of Spring Configuration
- Datasources
- Hibernate SessionFactories
- JPA EntityManagers and EntityManagerFactories
- Transaction management
5.2. Setting Up Data Access
5.2.1. Database Access Through Managed Datasources
EAP_HOME/standalone/configuration/standalone.xml configuration file either from the CLI or from the web console.
datasources subsystem.
Example 5.1. Managed Datasource Configuration in standalone.xml
<datasource jndi-name="java:jboss/datasources/ExampleDsJndiName" pool-name="ExampleDS" enabled="true"> <connection-url>jdbc:h2:mem:exampleDS</connection-url> <driver>h2</driver> <security> <user-name>sa</user-name> </security> </datasource>
java:jboss/datasources/ExampleDsJndiName. You can reference the datasource from a Spring ApplicationContext by using the definition in the example that follows. You can inject a datasource bean into any regular Spring bean (for example, a JBDS DAO).
Example 5.2. Defining a Managed Datasource Spring Bean
<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/ExampleDsJndiName" expected-type="javax.sql.DataSource"/>
5.2.2. Hibernate SessionFactory
Example 5.3. SessionFactory Bean Definition
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="datasource"/> ... </bean>
Example 5.4. JTA session management setup properties with Hibernate
hibernate.current_session_context_class=jta hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
Example 5.5. Hibernate-based DAO: a SessionFactory is Injected Directly in the Bean
public class HibernateAccountDao { @Autowired SessionFactory sessionFactory; public List<Account> getAllAccounts() { return sessionFactory.getCurrentSession().getCriteria(Account.class).list(); } ... }
5.3. Using JPA
- PersistenceUnit Deployed by the Container
- PersistenceUnit Created by Spring
- PersistenceContext and PersistenceUnit Injection
5.3.1. PersistenceUnit Deployed by the Container
web.xml file.
persistence.xml file:
Example 5.6. Persistence Unit Definition
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <persistence-unit name="sportsclubPU"> <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source> </persistence-unit> </persistence>
Example 5.7. Persistence context binding in JNDI
<web-app version="3.0" 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_3_0.xsd" metadata-complete="true"> <persistence-context-ref> <persistence-context-ref-name>example/em</persistence-context-ref-name> <persistence-unit-name>sportsclubPU</persistence-unit-name> </persistence-context-ref> </web-app>
Example 5.8. Spring Bean Representing a Container-managed Entity manager
<jee:jndi-lookup id="entityManager" jndi-name="java:comp/env/example/em"/>
Example 5.9. Hibernate-based DAO: a SessionFactory is Injected Directly in the Bean
public class HibernateAccountDao { @Autowired EntityManager entityManager; public List<Account> getAllAccounts() { return entityManager.createQuery("SELECT a FROM Account").getResultList(); } ... }
Example 5.10. Persistence unit binding in JNDI
<web-app version="3.0" 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_3_0.xsd" metadata-complete="true"> <persistence-unit-ref> <persistence-unit-ref-name>example/emf</persistence-unit-ref-name> <persistence-unit-name>sportsclubPU</persistence-unit-name> </persistence-unit-ref> </web-app>
Example 5.11. Spring Bean Representing an Entity Manager Factory
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:comp/env/example/emf"/>
5.3.2. PersistenceUnit Created by Spring
Example 5.12. A Spring Method Declaring a Read-Only Transaction
@Transaction(readOnly = true) public List<Account> getAllAccounts() { return entityManager.createQuery("SELECT a FROM Account").getResultList(); }
@Transactional(readOnly=true) flag causes Spring to allow it. Application performance increases as the persistence context is discarded at the end of the transaction. Support for this mode is not obligatory in Spring, and applications are not expected to rely on this behaviour at all times.
Example 5.13. A Spring-defined JTA-based Entity Manager Factory
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="jpaProperties"> <props> <prop key="hibernate.transaction.jta.platform"> org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform </prop> </props> </property> </bean>
META-INF/persistence.xml file, which contains the persistence unit definition, to be present in the deployment. JBoss Enterprise Application Platform automatically deploys the persistence unit from the persistence.xml file. However, if you require to create a Spring-based EntityManager rather than use the container-managed EntityManagerFactory, prevent JBoss Enterprise Application Platform from deploying the persistence unit. Use one of the following methods to achieve this:
- Configuring JBoss Enterprise Application Platform to not create EntityManagerFactory
- Renaming or moving the
persistence.xmlfile
persistence.xml file, set the value of jboss.as.jpa.managed property to false. This stops JBoss Enterprise Application Platform from creating the EntityManagerFactory. By default, this property is set to true, which enables container managed JPA access to the persistence unit.
Example 5.14. Configuring JBoss Enterprise Application Platform to not create EntityManagerFactory
<persistence 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_2_0.xsd" version="2.0"> <persistence-unit name="bookingDatabase"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>org.springframework.webflow.samples.booking.User</class> <class>org.springframework.webflow.samples.booking.Booking</class> <class>org.springframework.webflow.samples.booking.Hotel</class> <properties> <property name="jboss.as.jpa.managed" value="false"/> <!-- other properties (omitted) --> </properties> </persistence-unit> </persistence>
persistence.xml file and use the persistenceXmlLocation property as follows:
Example 5.15. Renaming or moving the Persistence.xml file
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-booking.xml"/> </bean>
persistence.xml file is located or what it is called, the WEB-INF/classes location is not scanned for persistent entries when the LocalContainerManagedEntityFactoryBean is used. In this case, the list of entities must be provided explicitly through one of the following methods:
- By enumerating the persistent classes in the
persistence.xmlfile (or other persistence unit configuration file name) - By packaging the entities in a JAR file and providing a <jar-file/> configuration entry in the
persistence.xmlfile - Using a PersistenceUnitPostprocessor
Example 5.16. Example of a PersistenceUnitPostProcessor Implementation That Adds all Classes Annotated with @Entity
package org.springframework.webflow.samples.booking; import java.io.IOException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo; import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor; public class MyPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor { @Autowired private ResourcePatternResolver resourceLoader; public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo mutablePersistenceUnitInfo) { try { Resource[] resources = resourceLoader.getResources("classpath:org/myexample/*.class"); for (Resource resource : resources) { CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory(); MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource); if (metadataReader.getAnnotationMetadata().isAnnotated(javax.persistence.Entity.class.getName())) { mutablePersistenceUnitInfo.addManagedClassName(metadataReader.getClassMetadata().getClassName()); } } mutablePersistenceUnitInfo.setExcludeUnlistedClasses(true); } catch (IOException e) { throw new RuntimeException(e); } } }
Example 5.17. Adding the PersistenceUnitPostProcessor to the Context Definition
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <!-- other properties --> <property name="persistenceUnitPostProcessors"> <list> <bean class="org.springframework.webflow.samples.booking.MyPersistenceUnitPostProcessor"/> </list> </property> </bean>
5.3.3. PersistenceContext and PersistenceUnit Injection
persistence.xml file to use a Spring-based EntityManagerFactory. However, the presence of @PersistenceContext or @PersistenceUnit annotations in Spring can cause deployment errors when the persistence.xml file is renamed. The errors occur because in a Java EE 6 environment, the @PersistenceContext and @PersistenceUnit annotations are used for supporting the container-driven injection of container-managed persistence contexts and persistence units, respectively. During deployment, Red Hat JBoss Enterprise Application Platform scans the deployment classes and validates for the presence of such annotations, the corresponding managed persistence units exist as well. This is not the case if the persistence.xml file is renamed.
Example 5.18. Metadata-complete Flag to Disable Class Scanning by Red Hat JBoss Enterprise Application Platform
<web-app version="3.0" 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_3_0.xsd" metadata-complete="true">
Example 5.19. SharedEntityManager Bean to Create an Injectable Transaction-aware EntityManager
<bean id="entityManagerWrapper" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean>
5.4. Transaction Management
Example 5.20. JTA Transaction Manager Definition in Spring
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManagerName" value="java:jboss/TransactionManager"/> </bean>
5.5. Messaging (JMS) Integration
Example 5.21. A message-driven POJO as a simple Java class with a single-argument method
public class MessageDrivenPojo { @Autowire PaymentProcessor paymentProcessor; public void pojoHandlerMethod(PaymentNotification paymentNotification) { paymentProcessor.processPayment(paymentNotification.getAccountNumber(), paymentNotification.getAmount()); } }
Example 5.22. JCA Message Listener Containers and Namespace Support in Red Hat JBoss Enterprise Application Platform
<jms:jca-listener-container resource-adapter="resourceAdapter" acknowledge="auto" activation-spec-factory="activationSpecFactory"> <jms:listener destination="/someDestination" ref="messageDrivenPojo" method="pojoHandlerMethod"/> </jms:jca-listener-container> <jboss:activation-spec-factory id="activationSpecFactory"/> <jboss:resource-adapter id="resourceAdapter"/> <bean id="messageDrivenPojo" class="example.MessageDrivenPojo"/>
5.6. JTA and Messaging Integration
5.7. EJB Integration
5.7.1. Injecting Spring Beans into EJBs
- Using Spring's native support for EJB integration
- Using Snowdrop with Spring
5.7.1.1. Using Spring's Native Support for EJB Integration
Example 5.23. Injecting Spring Bean into EJB Using Spring's Native Support
@Stateless @Interceptors(SpringBeanAutowiringInterceptor.class) public class InjectedEjbImpl implements InjectedEjb { @Autowired private SpringBean springBean; }
beanRefContext.xml on the classpath (that is, it performs a 'classpath*:beanRefContext.xml' lookup), which contains a single application context definition.
Example 5.24. Simple beanRefContext.xml File Used by a ContextSingletonBeanFactoryLocator and the Corresponding simpleContext.xml
<beans> <bean class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg value="classpath*:simpleContext.xml" /> </bean> </beans
<beans> <bean id="springBean" class="example.SpringBean"/> </beans>
5.7.1.2. Using Snowdrop with Spring
Example 5.25. Spring Beans Configuration File (example-spring.xml)
<beans> <description>BeanFactory=(MyApp)</description> <bean id="springBean" class="example.SpringBean"/> </beans>
Example 5.26. Injecting Spring Bean into EJB Using Snowdrop
@Stateless @Interceptors(SpringLifecycleInterceptor.class) public class InjectedEjbImpl implements InjectedEjb { @Spring(bean = "springBean", jndiName = "MyApp") private SpringBean springBean; /* rest of the class definition omitted */ }
5.7.2. Accessing EJBs from Spring Beans
- Using EJB reference bean definitions
- Using the @EJB annotation in Spring
<jee:local-slsb>/<jee:remote-slsb> elements.
Example 5.27. Defining EJB Reference as Spring Bean
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"> <jee:local-slsb id="ejbReference" jndi-name="java:global/example/example-ejb/ExampleImpl" business-interface="example.ExampleEjb"/> <bean id="consumerBean" class="example.ConsumerBean"> <property name="ejbReference" ref="ejbReference"/> </bean> </beans>
Example 5.28. Injecting EJB Reference Defined as Spring Bean
public class ConsumerBean { @Autowire ExampleEjb exampleEJB; }
Example 5.29. Injecting an EJB Using Annotations
public class ConsumerBean { @EJB(mappedName="java:global/example/example-ejb/ExampleImpl") ExampleEjb exampleEJB; }
5.8. Exceptions and Workarounds
5.8.1. Compatibility of Spring SAAJ, Oracle SAAJ, and IBM JDK
<dependency> <groupId>com.sun.xml.messaging.saaj</groupId> <artifactId>saaj-impl</artifactId> <version>1.3.10</version> </dependency>
<dependency> <groupId>com.sun.xml.parsers</groupId> <artifactId>jaxp-ri</artifactId> <version>1.4.5</version> </dependency>
Chapter 6. Spring in Action
6.1. About Spring Quickstarts
Quickstarts directory of every Red Hat JBoss Web Framework Kit release, for example:
- spring-greeter
- spring-kitchensink-basic
- spring-petclinic
- spring-resteasy
README.md file that details the prerequisites of the sample application, build and deploy instructions, and other related information. This chapter discusses the Spring Archetype example that uses the spring-kitchensink quickstart packaged in the JBoss Web Framework Kit distribution.
6.2. About the Spring Archetype example
- The general project structure of a Spring based web application
- A simple set of domain classes, MVC controllers, and web pages
- The data infrastructure configuration (including database, JPA, and transactions) for running Spring applications on JBoss Enterprise Application Platform
- Creating a project
- Adding source code
- Adding Spring configuration files
- Running the example
6.3. Prerequisites of the Spring Archetype example
- Maven 3.0.4
- Spring 4.1.4.RELEASE
- Red Hat JBoss Developer Studio 8
- Red Hat JBoss Enterprise Application Platform 6
Note
jboss-eap-6.
6.4. Creating the Spring Archetype Project
Procedure 6.1. Creating a Maven Project
- Start JBoss Developer Studio.
- Ensure you are using the JBoss perspective.
- Click →→.
- Enter the and click .
- Enter the and .
- Project name
- jboss-springmvc-webapp (that is the default)
- Package
- org.jboss.tools.example.springmvc (that is the default)
- Use default Workspace location
- (leave checked)
- Click . Confirm the , , , and .
- Group Id
- Automatically set to org.jboss.tools.example.springmvc
- Artifact Id
- jboss-springmvc-webapp
- Version
- 0.0.1-SNAPSHOT
- Package
- Automatically set to org.jboss.tools.example.springmvc
- Click .ResultYour project is created.
Procedure 6.2. Adding tool support for Spring
- In the view, select the tab.
- In the Features Available list, select the Spring IDE plug-in.
- Click .
6.5. Running the Spring Archetype Project
Procedure 6.3. Run the Example from the Command Line
- In the example directory, build the example with Maven.
cd $EXAMPLE_HOME mvn clean package
- Copy the example into your JBoss Enterprise Application Platform instance.
cp target/jboss-springmvc-webapp.war $EAP_HOME/standalone/deployments
- Run the JBoss Enterprise Application Platform instance.
$EAP_HOME/bin/standalone.sh
- After you have deployed the example, you can access it at http://localhost:8080/jboss-springmvc-webapp.
Procedure 6.4. Run the example from JBoss Developer Studio
- In the view, right-click the Spring Archetype project and click →. The window opens.
- From the list, select a JBoss Enterprise Application Platform 6 instance.
- Click .
- After the example is deployed, you can accessed it at http://localhost:8080/jboss-springmvc-webapp.
Chapter 7. Migrating Spring Applications
7.1. Migrating Spring Archives to Red Hat JBoss Enterprise Application Platform 6 from a Previous Version
Important
7.1.1. Server-deployed Persistence Unit
javax.persistence classes and the persistence provider, in this case Hibernate, are contained in modules which are added automatically by the application when the persistence unit is deployed. To use the server-deployed persistence units from within Spring, do one of the following:
- Register the JNDI persistence context in the
web.xmlfile: <persistence-context-ref> <persistence-context-ref-name>persistence/petclinic-em</persistence-unit-ref-name> <persistence-unit-name>petclinic</persistence-unit-name> </persistence-context-ref>
The persistence context is then available for JNDI lookup as follows: <jee:jndi-lookup id="entityManager" jndi-name="java:comp/env/persistence/petclinic-em" expected-type="javax.persistence.EntityManager"/>
- Register the JNDI persistence unit in the
web.xmlfile: <persistence-unit-ref> <persistence-unit-ref-name>persistence/petclinic-emf</persistence-unit-ref-name> <persistence-unit-name>petclinic</persistence-unit-name> </persistence-unit-ref> <persistence-unit-ref> <persistence-unit-ref-name>persistence/petclinic-emf</persistence-unit-ref-name> <persistence-unit-name>petclinic</persistence-unit-name> </persistence-unit-ref>
The persistence unit is then available for JNDI lookup as follows: <jee:jndi-lookup id="entityManagerFactory" jndi-name="java:comp/env/persistence/petclinic-emf" expected-type="javax.persistence.EntityManagerFactory"/>
Note
persistence.xml file properties is not supported in JBoss Enterprise Application Platform 6.
7.1.2. Spring-managed Persistence Unit
LocalContainerEntityManagerFactoryBean class. For such applications consider the following:
- Change the location of persistence unit definitionsWhen a deployment contains a
META-INF/persistence.xmlfile or aWEB-INF/classes/META-INF/persistence.xmlfile, the application server attempts to create a persistence unit based on the data in that file. In most cases, these definition files are not compliant with the Java EE requirements because the required elements (for example the datasource of the persistence unit) are expected to be provided by the Spring context definitions. This results in failure of deployment of the persistence unit and consequently of the entire deployment.You can avoid this problem by using a feature of theLocalContainerEntityManagerFactoryBeanthat is designed for this purpose. Persistence unit definition files can exist in other locations than theMETA-INF/persistence.xmlfile and the location can be indicated through thepersistenceXmlLocationproperty of the factory bean class.The following example assumes the persistence unit is in theMETA-INF/jpa-persistence.xmlfile: <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath*:META-INF/jpa-persistence.xml"/> <!-- other definitions --> </bean>
- Manage dependenciesIf using Hibernate with the application, the Hibernate 3 JARs must be included in the deployment. However, due to the presence of @PersistenceUnit or @PersistenceContext annotations on the application classes, the application server automatically adds the Hibernate 4
org.hibernatemodule as a dependency. You can instruct the server to exclude this module by creating aMETA-INF/jboss-deployment-structure.xmlfile (or aWEB-INF/jboss-deployment-structure.xmlfile for web applications) with the following content:<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2"> <deployment> <exclusions> <module name="org.hibernate"/> </exclusions> </deployment> </jboss-deployment-structure>
7.2. Migrating Spring to Red Hat JBoss Enterprise Application Platform from a Servlet Container
- Ensures that applications are compatible with the requirements of Java EE 6 standard
- Enables integration with the Red Hat JBoss middleware services provided by the container
- Avoids the inclusion of libraries that are provided by the application server
- Session factories
- Datasources
- Entity managers
7.2.1. Avoiding the Inclusion of Server-provided Dependencies
- The Java EE 6 APIs (like JPA, JSTL, and JMS)
- Hibernate (including Hibernate as a JPA provider)
- JSF
- Spring Framework
- Snowdrop
- Facelets
- RichFaces
7.2.2. Migrating Datasource Definitions
Example 7.1. Example commons-dbcp DataSource definition in a servlet container
<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://exampleHost/exampleDatabase" /> <property name="username" value="user" /> <property name="password" value="password" /> </bean>
Example 7.2. Using a JBoss Enterprise Application Platform managed datasource in Spring
<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/ExampleDS" expected-type="javax.sql.DataSource"/>
7.2.3. Migrating Hibernate SessionFactories to JTA
Example 7.3. SessionFactory and transaction manager definitions in a servlet environment
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations" value="classpath:**/*.hbm.xml"/> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect hibernate.show_sql=true </value> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
Example 7.4. JTA-based SessionFactory and transaction manager
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingLocations" value="classpath:**/*.hbm.xml"/> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect hibernate.show_sql=true hibernate.current_session_context_class=jta hibernate.transaction.jta.platform=org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory </value> </property> </bean> <tx:jta-transaction-manager id="transactionManager"/>
Note
7.2.4. Migrating JPA-based Applications
META-INF/persistence.xml file is automatically deployed by the container, but the container cannot declare a RESOURCE_LOCAL transaction type, and must include a JTA datasource reference. Also, the container may not specify a transaction type (which is equivalent to setting a JTA transaction type, but is ignored when the persistence unit is initialized by Spring and a resource-local model is used instead).
Example 7.5. A sample persistence unit definition for a servlet-container based application
<persistence-unit name="examplePU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/> </properties> </persistence-unit>
Example 7.6. JPA EntityManagerFactory and transaction setup in a servlet-container based application
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource"> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:database="${jpa.database}" p:showSql="${jpa.showSql}"/> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"/>
META-INF/persistence.xml file.
- rename the persistence unit definition file
- leave persistence-unit deployment to JBoss Enterprise Application Platform and use JNDI lookup for retrieving entity managers and entity manager factories.
Example 7.7. LocalContainerEntityManagerFactoryBean with alternate persistence.xml location
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath*:META-INF/jpa-persistence.xml"/> <!-- other properties (ommitted) --> </bean>
persistence.xml file definition to a JTA-based model and using JNDI lookup for retrieving the entity manager. For this, convert the persistence unit definition as in the following example (note that it is not necessary to provide values for both jboss.entity.manager.jndi.name and jboss.entity.manager.factory.jndi.name, but one must be specified).
Example 7.8. Changing the persistence.xml definition to be Java EE 6 compatible
<persistence-unit name="examplePU"> <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source> <properties> <property name="hibernate.show_sql" value="true"/> <property name="jboss.entity.manager.jndi.name" value="java:jboss/example/EntityManager"/> <property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/example/EntityManagerFactory"/> </properties> </persistence-unit>
Example 7.9. EntityManager retrieved by JNDI lookup and JTA transaction manager (works with @Autowired)
<jee:jndi-lookup id="entityManager" jndi-name="java:jboss/example/EntityManager" expected-type="javax.persistence.EntityManager"/> <tx:jta-transaction-manager/>
Example 7.10. EntityManagerFactory retrieved by JNDI lookup and JTA transaction manager (works with @PersistenceContext)
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:jboss/example/EntityManagerFactory" expected-type="javax.persistence.EntityManagerFactory"/> <tx:jta-transaction-manager/>
7.3. Migrating Spring PetClinic Example
web.xml file. This shows the migration strategies in each case, noting that only one of these strategies is used at a time.
spring-petclinic is distributed with this release of JBoss Web Framework Kit. It can be obtained from the JBoss Web Framework Kit quickstarts.zip file which is available to download from the Red Hat Customer Portal at https://access.redhat.com/ or from the JBoss Developer website at http://www.jboss.org/.
7.3.1. Preliminary Changes in Spring PetClinic Example
pom.xml file. Spring Petclinic uses Hibernate 4.3.8.Final, which is not supported on Red Hat JBoss Enterprise Application Platform 6.x. So, downgrade the version of Hibernate to a supported version. Change Hibernate version in the pom.xml file to 4.2.14.SP4-redhat-1.
Note
7.3.2. Build and Deploy the Spring PetClinic Application
- Run an instance of JBoss Enterprise Application Platform.
$EAP_HOME/bin/standalone.sh
- Navigate to the root directory of the Spring Petclinic application.
cd $spring-petclinic
- Build and deploy the application using Maven.
mvn clean package
- Copy
petclinic.warfile into the JBoss Enterprise Application Platform instance.cp petclinic-spring/target/petclinic.war $EAP_HOME/standalone/deployments/
After the example has been deployed, you can access it at http://localhost:8080/petclinic/.