Project

General

Profile

Sample-spring-hibernate » History » Version 13

Henning Blohm, 10.09.2015 15:28

1 1 Henning Blohm
h1. A sample using Hibernate and Spring on Z2
2
3 2 Henning Blohm
This sample is very similar to [[Sample-hibernate-basic]] but differs in that we use the Spring framework throughout...
4
5
* for assembly within the modules and to wire services between modules
6
* for declarative transaction demarcation
7
* for JPA entity manager injection 
8
9 3 Henning Blohm
This is another practical application of [[How to Spring]].
10
11 2 Henning Blohm
This sample is stored in "z2-samples.spring-hibernate":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate.
12
13 12 Henning Blohm
Check out [[How to transaction management]] for more infos on transaction management on Z2. See related examples 
14
15
* [[Sample-springds-hibernate]] for an even tighter Spring embrace, 
16
* [[Sample-jta-spring]] for integration with a third-party transaction manager
17
* [[Sample-spring-basic]] for a starter on Spring integration with Z2
18
 
19 2 Henning Blohm
h2. Prerequisites
20
21 13 Henning Blohm
You need is a JDK 6 or JDK 7 distribution as described in [[Step_2_-_Install_and_run_in_5_minutes]].
22
23
*NOTE:* All versions less than 3 will not run with Java 8. You need to use Java 7 instead!
24
25 11 Henning Blohm
You need to run Java DB as network server on localhost. This is explained next.
26 2 Henning Blohm
27 11 Henning Blohm
The application will create a database "z2-samples"
28
29
{{include(How to run Java db)}}
30
31 2 Henning Blohm
32
h2. Run it
33
34
Like all samples, also this sample can be run as in [[How to run a sample]]. If you have the database, the fastest way to verify whether it runs is:
35
36
<pre><code class="ruby">
37
mkdir install
38
cd install 
39
git clone -b master http://git.z2-environment.net/z2-base.core
40
git clone -b master http://git.z2-environment.net/z2-samples.spring-hibernate
41
42
# on Linux / Mac OS:
43
cd z2-base.core/run/bin
44
./gui.sh
45
46
# on Windows:
47
cd z2-base.core\run\bin
48
gui.bat
49
</code></pre>
50
51
When running, go to http://localhost:8080/spring-hibernate. You should see this:
52
53
!spring-hibernate.png!
54 3 Henning Blohm
55
h2. Details
56
57
Similar to [[Sample-hibernate-basic]], the assumption of this example is that of a re-use domain module *com.zfabrik.samples.spring-hibernate.domain* that implements a "Thingy Repository" and is used from a web application that is in another module *com.zfabrik.samples.spring-hibernate.web*. The domain module exposes the Thingy Repository as a Z2 component - from a Spring application context defined bean -  that is imported into the application context of the Web application and injected into the controller filter by Spring. The controller uses declarative transaction demarcation.
58
59
The domain module makes use of Hibernate's JPA implementation using Spring's entity manager injection and integrates with the transaction management provided by *com.zfabrik.jta*.
60
61
h3. The domain module and its persistence context
62
63
The domain module *com.zfabrik.samples.spring-hibernate.domain* defines a persistence unit "thingies" in "java/src.impl/META-INF/persistence.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/META-INF/persistence.xml, i.e. in its implementation. That makes sense, as the XML file will be looked up with a class loader and we do not intent to retrieve from another module. Or, put differently, the persistence unit is not part of the module's API.
64
65
In order to integrate with the built-in transaction management the <code>persistence.xml</code> declares the JTA data source 
66
67
<pre><code class="xml">
68 8 Henning Blohm
<jta-data-source>components:com.zfabrik.samples.spring-hibernate.domain/DB</jta-data-source>
69 3 Henning Blohm
</code></pre>
70
71
and the _Transaction Manager Lookup_ 
72
73
<pre><code class="xml">
74
<property name="hibernate.transaction.manager_lookup_class" value="com.zfabrik.hibernate.TransactionManagerLookup" />
75
</code></pre>
76
77 8 Henning Blohm
The former points to the data source component "com.zfabrik.samples.spring-hibernate.domain/DB":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/DB.properties, while the latter makes sure Hibernate can register with the transaction manager implementation. 
78 3 Henning Blohm
79
The persistence unit defines only one entity. The Thingy as in "Thingy.java":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.api/com/zfabrik/samples/spring_hibernate/thingies/Thingy.java. That is an API-exposed type. We use the simplified pattern of exposing persistent objects in the API rather than using Data Transfer Objects (DTOs).
80
81
The application context of the module is defined in "java/src.impl/META-INF/applicationContext.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/META-INF/applicationContext.xml and looks like this:
82
83
<pre><code class="xml">
84
<?xml version="1.0" encoding="UTF-8"?>
85
<beans xmlns="http://www.springframework.org/schema/beans"
86
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
87
	xmlns:context="http://www.springframework.org/schema/context"
88
	xmlns:aop="http://www.springframework.org/schema/aop"
89
	xsi:schemaLocation="
90
	http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
91
	http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  
92
	http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
93
	http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
94
95
	<!-- annotation based config -->
96
	<context:component-scan base-package="com.zfabrik.samples.spring_hibernate" />
97
	<context:annotation-config />
98
99
	<!-- EntityManager injection -->
100
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
101
102
	<!-- The actual EMF we use -->
103
	<bean id="entityManagerFactory"	class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
104
		<property name="persistenceUnitName" value="thingies" />
105
	</bean>
106
    
107
</beans>
108
</code></pre>
109
110
In short: 
111
* We make sure we can use annotations
112
* We enable entity manager injection
113
* We initialize the entity manager factory from Spring
114
115 8 Henning Blohm
In the implementation class "ThingyRepositoryImpl":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/com/zfabrik/samples/spring_hibernate/impl/thingies/ThingyRepositoryImpl.java we make use of these capabilities and declare a Spring bean "thingyRepository":
116 3 Henning Blohm
117
<pre><code class="java">
118 9 Henning Blohm
@Repository("thingyRepository")
119 3 Henning Blohm
public class ThingyRepositoryImpl implements ThingyRepository {
120
	@PersistenceContext
121
	private EntityManager em;
122
123
	@Override
124
	public void store(Thingy thingy) {
125
		this.em.persist(thingy);
126
	}
127
128
	@SuppressWarnings("unchecked")
129
	@Override
130
	public Collection<Thingy> findAll() {
131
		return this.em.createQuery("select t from Thingy t").getResultList();
132
	}
133
134
	@Override
135
	public void delete(int id) {
136
		Thingy t = this.em.find(Thingy.class, id);
137
		if (t != null) {
138
			this.em.remove(t);
139
		}
140
	}
141
}
142
</code></pre>
143
144
In order to expose that bean as a Z2 component for re-use from other modules, we declare a component "com.zfabrik.samples.spring-hibernate/repository":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/repository.properties:
145
146
<pre><code class="ruby"> 
147
com.zfabrik.component.type=org.springframework.bean
148
149
#
150
# Expose Spring defined data source
151
#
152
153
#
154
# the context that defines the bean (more than one
155
# bean can be exposed like this)
156
#
157
bean.context=com.zfabrik.samples.spring-hibernate.domain/applicationContext
158
159
#
160
# the bean name
161
#
162 10 Henning Blohm
bean.name=thingyRepository
163 3 Henning Blohm
</code></pre>
164
165
that is based on the application context component "com.zfabrik.samples.spring-hibernate/applicationContext":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/applicationContext.properties:
166
167
<pre><code class="ruby"> 
168
com.zfabrik.component.type=org.springframework.context
169
170
#
171
# context config location is where the context is 
172
# actually defined. 
173
#
174
context.contextConfigLocation=classpath:META-INF/applicationContext.xml
175
</code></pre>
176
177
See also [[How to Spring]] for more details on these component types.
178 4 Henning Blohm
179
h3. The web module, transaction boundaries, and service re-use
180
181
Let's turn to the Web application in *com.zfabrik.samples.spring-hibernate.web/web*. This one is also Spring configured. In contrast to the service module, its application context is not initialized from a Z2 component but rather from the Web app context (see "web/WebContent/WEB-INF/web.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.web/web/WebContent/WEB-INF/web.xml). It is stored in "web/WebContent/WEB-INF/applicationContext.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.web/web/WebContent/WEB-INF/applicationContext.xml and looks like this:
182
183
<pre><code class="xml">
184
<?xml version="1.0" encoding="UTF-8"?>
185
<beans xmlns="http://www.springframework.org/schema/beans"
186
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
187
	xmlns:context="http://www.springframework.org/schema/context"
188
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:security="http://www.springframework.org/schema/security"
189
	xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
190
	http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  
191
	http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
192
	http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
193
	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
194
195
	<!-- Annotation Support -->
196
	<context:component-scan base-package="com.zfabrik.samples.spring_hibernate" />
197
	<context:spring-configured />
198
	<context:annotation-config />		
199
200
	<!--  
201
	This binds to java:comp/UserTransaction, which is ok in a Web app and considering
202
	that we configured Jetty JTA (see the transaction manager how-to in the Z2 Wiki and check environment/webServer/jetty.xml)
203
    -->
204
	
205
	<tx:jta-transaction-manager/>
206
207
    <!-- outside of a web app we would bind to com.zfabrik.jta transaction manager like this
208
209
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
210
	    <property name="userTransaction">
211
	        <bean class="com.zfabrik.tx.UserTransaction"/>
212
	    </property>
213
	</bean>
214
	 -->
215
216 8 Henning Blohm
	<!-- make sure we can use @Transactional with the Spring aspect -->
217 4 Henning Blohm
	<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
218
219
	<!-- import external services -->
220
    <bean id="thingyRepository" class="com.zfabrik.springframework.ComponentFactoryBean">
221
        <property name="componentName"  value="com.zfabrik.samples.spring-hibernate.domain/repository" />
222
        <property name="className"  value="com.zfabrik.samples.spring_hibernate.thingies.ThingyRepository" />
223
    </bean>
224
	
225
</beans>
226
227
</code></pre>
228
229
In short:
230
231
* We enable annotation based configuration
232 7 Henning Blohm
* We make the transaction manager available (for in-depth details see [[How to transaction management]])
233 8 Henning Blohm
* We enabled annotation based transaction demarcation (i.e. the use of <code>@Transactional</code>)
234 4 Henning Blohm
* We import the Thingy Repository as a bean into this context.
235
236 8 Henning Blohm
The "ControllerFilter":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.web/java/src.impl/com/zfabrik/samples/spring_hibernate/impl/web/ControllerFilter.java is configured by Spring, although it is instantiated by the Jetty Web container. That is happening because we use the Spring aspect (see [[How to Spring]] once more) and it is annotated with <code>@Configurable</code>. We let Spring inject the Thingy Repository and we mark the <code>doFilter</code> method as transactional. Here is its skeleton:
237 4 Henning Blohm
238 5 Henning Blohm
<pre><code class="java">
239
@Configurable
240
public class ControllerFilter implements Filter {
241 4 Henning Blohm
242 5 Henning Blohm
  @Autowired
243
  private ThingyRepository thingyRepository;
244
	
245
  @Transactional
246
  public void doFilter(ServletRequest sreq, ServletResponse sres,	FilterChain chain) throws IOException, ServletException {
247
    
248
    // do some work here
249 1 Henning Blohm
250 5 Henning Blohm
  }
251
252
  @Override
253
  public void init(FilterConfig cfg) throws ServletException {}
254
  
255
  @Override
256
  public void destroy() {}
257
}
258
</code></pre>
259 6 Henning Blohm
260
h2. A final word
261
262
A lot of what happens here requires the right libraries to be available in the sample modules. These are provided via the references in the <code>z.properties</code> files in the respective Java modules. 
263
In other words: There is some non-trivial mechanics going on here that - in the long run - you should be aware of and try to read carefully through [[How to Spring]]. As a result you get a lot of coding and modularization convenience in the combination of Spring and Z2.