Project

General

Profile

Sample-vaadin-spring-hibernate » History » Version 1

Henning Blohm, 06.10.2012 13:39

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