Project

General

Profile

Sample-spring-hibernate » History » Version 16

Henning Blohm, 18.09.2018 21:43

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 14 Henning Blohm
{{include(Java Version Requirements)}}
22 13 Henning Blohm
23 11 Henning Blohm
You need to run Java DB as network server on localhost. This is explained next.
24 2 Henning Blohm
25 11 Henning Blohm
The application will create a database "z2-samples"
26
27
{{include(How to run Java db)}}
28
29 2 Henning Blohm
30
h2. Run it
31
32 16 Henning Blohm
If you have the database, the fastest way to verify whether it runs is:
33 1 Henning Blohm
34 16 Henning Blohm
{{include(Install_sample_prefix)}}
35 2 Henning Blohm
36 16 Henning Blohm
Check out the sample
37 2 Henning Blohm
38 16 Henning Blohm
<pre><code class="ruby">
39
git clone -b v2.6 http://git.z2-environment.net/z2-samples.spring-hibernate
40 2 Henning Blohm
</code></pre>
41 16 Henning Blohm
42
{{include(Install_sample_postfix)}}
43 2 Henning Blohm
44
When running, go to http://localhost:8080/spring-hibernate. You should see this:
45
46
!spring-hibernate.png!
47 3 Henning Blohm
48
h2. Details
49
50
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.
51
52
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*.
53
54
h3. The domain module and its persistence context
55
56
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.
57
58
In order to integrate with the built-in transaction management the <code>persistence.xml</code> declares the JTA data source 
59
60
<pre><code class="xml">
61 8 Henning Blohm
<jta-data-source>components:com.zfabrik.samples.spring-hibernate.domain/DB</jta-data-source>
62 3 Henning Blohm
</code></pre>
63
64
and the _Transaction Manager Lookup_ 
65
66
<pre><code class="xml">
67
<property name="hibernate.transaction.manager_lookup_class" value="com.zfabrik.hibernate.TransactionManagerLookup" />
68
</code></pre>
69
70 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. 
71 3 Henning Blohm
72
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).
73
74
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:
75
76
<pre><code class="xml">
77
<?xml version="1.0" encoding="UTF-8"?>
78
<beans xmlns="http://www.springframework.org/schema/beans"
79
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
80
	xmlns:context="http://www.springframework.org/schema/context"
81
	xmlns:aop="http://www.springframework.org/schema/aop"
82
	xsi:schemaLocation="
83
	http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
84
	http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  
85
	http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
86
	http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
87
88
	<!-- annotation based config -->
89
	<context:component-scan base-package="com.zfabrik.samples.spring_hibernate" />
90
	<context:annotation-config />
91
92
	<!-- EntityManager injection -->
93
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
94
95
	<!-- The actual EMF we use -->
96
	<bean id="entityManagerFactory"	class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
97
		<property name="persistenceUnitName" value="thingies" />
98
	</bean>
99
    
100
</beans>
101
</code></pre>
102
103
In short: 
104
* We make sure we can use annotations
105
* We enable entity manager injection
106
* We initialize the entity manager factory from Spring
107
108 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":
109 3 Henning Blohm
110
<pre><code class="java">
111 9 Henning Blohm
@Repository("thingyRepository")
112 3 Henning Blohm
public class ThingyRepositoryImpl implements ThingyRepository {
113
	@PersistenceContext
114
	private EntityManager em;
115
116
	@Override
117
	public void store(Thingy thingy) {
118
		this.em.persist(thingy);
119
	}
120
121
	@SuppressWarnings("unchecked")
122
	@Override
123
	public Collection<Thingy> findAll() {
124
		return this.em.createQuery("select t from Thingy t").getResultList();
125
	}
126
127
	@Override
128
	public void delete(int id) {
129
		Thingy t = this.em.find(Thingy.class, id);
130
		if (t != null) {
131
			this.em.remove(t);
132
		}
133
	}
134
}
135
</code></pre>
136
137
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:
138
139
<pre><code class="ruby"> 
140
com.zfabrik.component.type=org.springframework.bean
141
142
#
143
# Expose Spring defined data source
144
#
145
146
#
147
# the context that defines the bean (more than one
148
# bean can be exposed like this)
149
#
150
bean.context=com.zfabrik.samples.spring-hibernate.domain/applicationContext
151
152
#
153
# the bean name
154
#
155 10 Henning Blohm
bean.name=thingyRepository
156 3 Henning Blohm
</code></pre>
157
158
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:
159
160
<pre><code class="ruby"> 
161
com.zfabrik.component.type=org.springframework.context
162
163
#
164
# context config location is where the context is 
165
# actually defined. 
166
#
167
context.contextConfigLocation=classpath:META-INF/applicationContext.xml
168
</code></pre>
169
170
See also [[How to Spring]] for more details on these component types.
171 4 Henning Blohm
172
h3. The web module, transaction boundaries, and service re-use
173
174
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:
175
176
<pre><code class="xml">
177
<?xml version="1.0" encoding="UTF-8"?>
178
<beans xmlns="http://www.springframework.org/schema/beans"
179
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
180
	xmlns:context="http://www.springframework.org/schema/context"
181
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:security="http://www.springframework.org/schema/security"
182
	xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
183
	http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  
184
	http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
185
	http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
186
	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
187
188
	<!-- Annotation Support -->
189
	<context:component-scan base-package="com.zfabrik.samples.spring_hibernate" />
190
	<context:spring-configured />
191
	<context:annotation-config />		
192
193
	<!--  
194
	This binds to java:comp/UserTransaction, which is ok in a Web app and considering
195
	that we configured Jetty JTA (see the transaction manager how-to in the Z2 Wiki and check environment/webServer/jetty.xml)
196
    -->
197
	
198
	<tx:jta-transaction-manager/>
199
200
    <!-- outside of a web app we would bind to com.zfabrik.jta transaction manager like this
201
202
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
203
	    <property name="userTransaction">
204
	        <bean class="com.zfabrik.tx.UserTransaction"/>
205
	    </property>
206
	</bean>
207
	 -->
208
209 8 Henning Blohm
	<!-- make sure we can use @Transactional with the Spring aspect -->
210 4 Henning Blohm
	<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
211
212
	<!-- import external services -->
213
    <bean id="thingyRepository" class="com.zfabrik.springframework.ComponentFactoryBean">
214
        <property name="componentName"  value="com.zfabrik.samples.spring-hibernate.domain/repository" />
215
        <property name="className"  value="com.zfabrik.samples.spring_hibernate.thingies.ThingyRepository" />
216
    </bean>
217
	
218
</beans>
219
220
</code></pre>
221
222
In short:
223
224
* We enable annotation based configuration
225 7 Henning Blohm
* We make the transaction manager available (for in-depth details see [[How to transaction management]])
226 8 Henning Blohm
* We enabled annotation based transaction demarcation (i.e. the use of <code>@Transactional</code>)
227 4 Henning Blohm
* We import the Thingy Repository as a bean into this context.
228
229 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:
230 4 Henning Blohm
231 5 Henning Blohm
<pre><code class="java">
232
@Configurable
233
public class ControllerFilter implements Filter {
234 4 Henning Blohm
235 5 Henning Blohm
  @Autowired
236
  private ThingyRepository thingyRepository;
237
	
238
  @Transactional
239
  public void doFilter(ServletRequest sreq, ServletResponse sres,	FilterChain chain) throws IOException, ServletException {
240
    
241
    // do some work here
242 1 Henning Blohm
243 5 Henning Blohm
  }
244
245
  @Override
246
  public void init(FilterConfig cfg) throws ServletException {}
247
  
248
  @Override
249
  public void destroy() {}
250
}
251
</code></pre>
252 6 Henning Blohm
253
h2. A final word
254
255
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. 
256
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.