Project

General

Profile

How to Spring » History » Version 61

Henning Blohm, 09.05.2014 21:50

1 39 Henning Blohm
h1. How to use the Spring framework in Z2
2 16 Henning Blohm
3 37 Henning Blohm
There is actually nothing really particular about using Spring in Z2. But when knowing how Z2 modularity works, there is much to gain by spending a few minutes reading this Howto. We assume however that you are familiar with the Spring framework as such.
4 2 Henning Blohm
5 57 Henning Blohm
It may be best to inspect the the basic [[Sample-spring-basic]] sample in parallel to reading this page, as that makes use of most of what you will find here and is still really simple. Plus, running the sample requires no more than an IDE and five minutes of your time.
6 1 Henning Blohm
7 58 Henning Blohm
Other samples highlight specific integrations that may be of interest to you:
8 53 Henning Blohm
9
* [[Sample-spring-hibernate]] shows how to use Spring with Hibernate and Z2's built-in basic transaction management,
10
* [[Sample-jta-spring]] shows how to use Spring with Hibernate and the Atomikos transaction manager,
11 58 Henning Blohm
* [[Sample-springds-hibernate]] shows how to use Spring with Hibernate and Spring's basic basic transaction management,
12 53 Henning Blohm
13 58 Henning Blohm
(and by here you should have noted that transaction handling is obviously a noteworthy cross-cutting concern)
14 53 Henning Blohm
15
* [[Sample-vaadin-spring-hibernate]] shows a blueprint for a rich-internet-application built on Vaadin, Spring, and Hibernate
16
 
17 58 Henning Blohm
Please also check the add-on page [[Spring add-on]]. The Spring add-on should be considered an example on how to make use of Spring with Z2. It adds extremely useful support functionality for a seamless aspectj-driven annotation based application configuration - turning the combination of Z2 and Spring into a first-class, flexible, extensible, productive, and scalable application server environment.
18 44 Henning Blohm
19 38 Henning Blohm
h2. Pre-requisites
20 1 Henning Blohm
21 54 Henning Blohm
In order to have the Spring libraries available you need to add the add-on [[Spring add-on]] via the repository "z2-addons.spring":http://redmine.z2-environment.net/projects/z2-addons/repository/z2-addons-spring to your environment (the samples do so in their _environment_).  To use the master branch version, add a *springAddon.properties* component descriptor to your *environment* module saying
22 2 Henning Blohm
23 17 Henning Blohm
<pre><code class="python">
24 15 Henning Blohm
com.zfabrik.systemStates.participation=com.zfabrik.boot.main/sysrepo_up
25 3 Henning Blohm
26
# git stored component repository
27
com.zfabrik.component.type=com.zfabrik.gitcr
28
29
# true <=> optional repository. If gitcr.uri is invalid, then this gitcr will be ignore silently  
30
gitcr.optional=true
31
32
# this can also point to a remote repository like 
33
# ssh://myserver/some/git/repo
34
gitcr.uri=http://git.z2-environment.net/z2-addons.spring
35
# the git branch to use (e.g. 'master')
36
gitcr.branch=master
37
</code></pre>
38 15 Henning Blohm
39 58 Henning Blohm
(this declaration referring to our Git repository - you need to adapt, if you want to work with your clones)
40 3 Henning Blohm
41 58 Henning Blohm
If that sounds like meaningless gibberish to you: Sorry! Please consult the documentation at http://www.z2-environment.eu/v21doc and go back to [[First_steps_with_z2]].
42 45 Henning Blohm
43 58 Henning Blohm
In addition, as of v2.3, you need to declare a Maven component repository *environment/mavenDefault* in order to guide Z2 in retrieving remote Maven artifacts. This is what all samples do, as for example [[Sample-spring-basic]] in "environment/mavenDefault":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/show/environment/mavenDefault.
44 1 Henning Blohm
45 58 Henning Blohm
To get started, it will be best to start from one of the samples.
46 4 Henning Blohm
47 58 Henning Blohm
Once you added that repository the following Z2 modules are available from the add-on:
48 54 Henning Blohm
49 1 Henning Blohm
* org.springframework.orm
50 55 Henning Blohm
* org.springframework.tx
51 1 Henning Blohm
* org.springframework.jdbc         
52
* com.zfabrik.springframework      
53
* com.zfabrik.springframework.web  
54
55 54 Henning Blohm
These are in fact assembly modules built from maven artifacts that are (by virtue of the maven component repo) available in Z2 as well (see [[How to Access a Maven Repository]] for more details). Specifically these are (at the time of writing):
56 1 Henning Blohm
57 61 Henning Blohm
* org.springframework.security:spring-security-aspects
58
* org.springframework.security:spring-security-config
59
* org.springframework.security:spring-security-core
60
* org.springframework.security:spring-security-web
61 54 Henning Blohm
* org.springframework:spring-aop
62
* org.springframework:spring-aspects
63
* org.springframework:spring-beans
64
* org.springframework:spring-context
65 61 Henning Blohm
* org.springframework:spring-context-support
66 54 Henning Blohm
* org.springframework:spring-core
67
* org.springframework:spring-expression
68
* org.springframework:spring-jdbc
69
* org.springframework:spring-orm
70
* org.springframework:spring-tx
71
* org.springframework:spring-web
72 38 Henning Blohm
73 54 Henning Blohm
These Z2 Java components are representing exactly the Spring artifacts distributed by Springsource.
74 1 Henning Blohm
75 54 Henning Blohm
Before you get frustrated by the amount of details in this Howto, please remember the samples above: In the end it boils down to just using things correctly (and then repeatedly).
76 5 Henning Blohm
77
h2. Using Spring in Web applications
78
79
This is the simplest and really just the standard case. If you do not strive for re-use across modules that use Spring, then there is not much to worry about. 
80 17 Henning Blohm
81 5 Henning Blohm
As usual, you define an application context in the WEB-INF folder of the Web application and set up a context listener in WEB-INF/web.xml to have the application 
82
context initialized as the Web app is started.
83 1 Henning Blohm
84 5 Henning Blohm
In order to have the minimal set of dependencies satisfied - i.e. not assuming you want to use the (very cool) AspectJ based Spring configuration, you should _add_ (i.e. augment whatever refs you already have) the following references to *java/z.properties*:
85 1 Henning Blohm
86 11 Henning Blohm
<pre><code class="python">
87 5 Henning Blohm
java.privateReferences=\
88 54 Henning Blohm
	com.zfabrik.springframework.web
89 5 Henning Blohm
</code></pre>
90
91 7 Henning Blohm
The reference to *com.zfabrik.springframework.web* is not strictly needed but adds the following capabilities:
92 5 Henning Blohm
93 7 Henning Blohm
* You implicitly get *com.zfabrik.springframework*, i.e. the integration features described below
94
* You can use a parent application context to your Web application application context as easily as you would hope (see below).
95 49 Henning Blohm
96
h2. Using Spring in re-use modules
97 38 Henning Blohm
98 19 Henning Blohm
When going modular, you will leave the pure "Spring in a Web Application" path. That is, you may want to use Spring in modules that expose components and APIs to other modules. For example to implement shared services that are used in more than one Web Application, or for example to implement scheduled job execution.
99 20 Henning Blohm
100 55 Henning Blohm
*Define an Application Context in a Java Module for re-use*
101 20 Henning Blohm
102
In that case, you will not define an application context in a WEB-INF folder (as there most likely is none) but instead you will define a class path defined application context, or more specifically you will put your application context (most likely) in *java/src.impl/META-INF/applicationContext.xml* of your re-use module.
103
104 1 Henning Blohm
*Starting an Application Context*
105 21 Henning Blohm
106 55 Henning Blohm
Now that you have that application context, you need to make sure it gets started, when you need it up. If you went this far, there is good reasons you use Z2 runtime dependencies to start it. Pre-requisite for that is to have the application context declared as a Z2 component. So you create a file *applicationContext.properties* in your module saying
107 21 Henning Blohm
108
<pre><code class="python">
109
com.zfabrik.component.type=org.springframework.context
110
111
#
112 1 Henning Blohm
# context config location is where the context is 
113 21 Henning Blohm
# actually defined. 
114
#
115
context.contextConfigLocation=classpath:META-INF/applicationContext.xml
116 1 Henning Blohm
</code></pre>
117
118 59 Henning Blohm
Once it is defined as a component, you can have it started via a "system state dependency":http://www.z2-environment.eu/v20doc#System%20States%20(core) or via a "generic component depencency":http://www.z2-environment.eu/v20doc#CoreComponentProps.
119 22 Henning Blohm
120
Another way is to have it started implicitly from a bean component declaration. In that case, before providing the bean instance, the application context will be initialized.
121 19 Henning Blohm
122 38 Henning Blohm
*Exposing a bean from an application context*
123 23 Henning Blohm
124
Now that you have declared an application context component, you can actually expose beans from it as Z2 components that may be looked up from other modules. To do so, create a component like this:
125 1 Henning Blohm
126 23 Henning Blohm
<pre><code class="python">
127
com.zfabrik.component.type=org.springframework.bean
128
129 1 Henning Blohm
#
130 23 Henning Blohm
# the context that defines the bean (more than one
131 1 Henning Blohm
# bean can be exposed like this)
132 23 Henning Blohm
#
133
bean.context=<module name>/applicationContext
134
135
#
136 24 Henning Blohm
# the bean name
137 23 Henning Blohm
#
138 1 Henning Blohm
bean.name=<bean name>
139 23 Henning Blohm
</code></pre>
140
141 55 Henning Blohm
Once a bean has been made available to other modules, the next natural question is how to actually refer to a Z2 component from a Spring application context.
142 23 Henning Blohm
143 25 Henning Blohm
*Importing a bean or just any component*
144 23 Henning Blohm
145
The module *com.zfabrik.springframework* contains a factory bean that just does that. Assuming you want to use component &lt;module&gt;/&lt;name&gt; which is of type (or has super type) my.Class, you would add to your importing application context:
146
147
<pre><code class="xml">
148 1 Henning Blohm
<bean id="beanId" class="com.zfabrik.springframework.ComponentFactoryBean">
149
  <property name="componentName" value="<module>/<name>" />
150
  <property name="className" value="my.Class" />
151 25 Henning Blohm
</bean>
152 1 Henning Blohm
</code></pre>
153 25 Henning Blohm
154 55 Henning Blohm
Ok, so far so good. Let's see how we can some more configuration magic to all of this.
155 25 Henning Blohm
156
h2. Using Spring's AspectJ configuration
157 23 Henning Blohm
158 59 Henning Blohm
By default, Spring's annotation support reaches as far as Spring "can see". That is, objects instantiated outside of Spring's control will not be subject to Spring configuration - simply because Spring has no chance to notice their instantiation. 
159 2 Henning Blohm
160 55 Henning Blohm
When using Spring's AspectJ feature, Spring's configuration reach can be extended to virtually anything within the implementation scope. Normally, configuring your build to include the AspectJ compilation can be tricky and tiring. Using load-time-weaving is rather error-prone as types may not have been loaded before the aspect has been registered - something where you can so easily fool yourself.
161 46 Udo Offermann
162 27 Henning Blohm
Fortunately for you, the Spring integration features of Z2 also provide a compiler extension for Spring with AspectJ. To use it, you need to modify your *java/z.properties* to reflect the following includes and refs and in particular the compiler settings:
163
164
<pre><code class="python">
165
java.privateReferences=\
166
	com.zfabrik.springframework,\
167 55 Henning Blohm
	org.springframework.tx,\
168
	org.springframework.orm
169 27 Henning Blohm
170
java.privateIncludes=\
171 55 Henning Blohm
	org.springframework:spring-aspects
172 27 Henning Blohm
	
173
java.compile.order=java,spring_aspectj
174
</code></pre>
175
176
The refs to spring transaction and spring ORM look unintuitive. And they are. At the time of this writing the Spring aspect unfortunately still required those.
177
178 55 Henning Blohm
Note the use of @java.privateIncludes@. In order to isolate application contexts from different modules at runtime, the spring aspect library needs to be included rather than referenced (see the next section). Simply consider the declarations above a blueprint, boilerplate declaration template for using Spring configuration in an implementation of a Z2 Java module.
179
180 27 Henning Blohm
When you have applied the configuration above, you can make any type Spring configurable by annotating it with <code>@Configurable</code>. For example the "ControllerServlet":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.frontend/java/src.impl/com/zfabrik/samples/impl/frontend/ControllerServlet.java in the sample *z2-samples.spring-basic* has the following skeleton:
181
182 1 Henning Blohm
<pre><code class="java">
183 41 Henning Blohm
@Configurable
184
public class ControllerServlet extends HttpServlet {
185
        @Autowired
186 27 Henning Blohm
        private IComputationService computations;
187 1 Henning Blohm
188 41 Henning Blohm
        @Override
189
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
190 1 Henning Blohm
            //...
191 41 Henning Blohm
        }
192
193 1 Henning Blohm
}
194
195
</code></pre>
196
197
Now that all complexity of AspectJ compilation is completely out of the way, using Spring AspectJ can realize all its advantages over regular Spring AOP. Most notably, Spring AspectJ does not require proxy objects as Spring AOP does. This has a lot of simplifying implications. For example, annotations like @Transactional now work regardless of who is calling (inside or outside) and what methods are annotated. Similarly, other annotations such as those of Spring security work as naively expected. 
198
199 41 Henning Blohm
*Simply put: Spring AspectJ does it right where Spring AOP could not due to technical limitations.*
200 27 Henning Blohm
201 41 Henning Blohm
The whole subject is not completely trivial. For a deeper understanding we suggest to read:
202 27 Henning Blohm
203 26 Henning Blohm
* "Aspect Oriented Programming with Spring (Springsource)":http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-ataspectj
204 50 Henning Blohm
* "A starting point for pro and cons discussion (Stackoverflow)":http://stackoverflow.com/questions/1606559/spring-aop-vs-aspectj
205 1 Henning Blohm
* "Pitfalls of Spring proxying (external blog)":http://nurkiewicz.blogspot.de/2011/10/spring-pitfalls-proxying.html
206 50 Henning Blohm
207
h3. Making sure to configure for Spring AspectJ correctly
208
209
In order to avoid proxying when using Spring AspectJ, which you should to have one consistent approach, make sure that you apply a @mode="aspectj"@ attribute where possible.
210
211
This includes:
212
213
* the @<tx:annotation-driven/>@ annotation. Make sure it reads @<tx:annotation-driven mode="aspectj"/>@ (and possibly other attributes)
214
* the @<security:global-method-security/>@ annotation. Make sure it reads @<security:global-method-security mode="aspectj"/>@ (and possibly other attributes)
215
216
Use of the Spring aspects require to include the matching aspect libraries. In particular:
217
218
* When using Spring security aspects, add @org.springframework.security/aspects@ to your private includes
219
220
For example, an advanced Spring usage java component configuration may look like this:
221
222
<pre><code class="python">
223 52 Henning Blohm
com.zfabrik.component.type=com.zfabrik.java
224
java.privateReferences=\
225 55 Henning Blohm
    com.zfabrik.springframework,\
226 52 Henning Blohm
    org.springframework.orm,\
227
    org.springframework.web,\
228 55 Henning Blohm
    org.springframework.tx
229 50 Henning Blohm
230
java.privateIncludes=\
231 55 Henning Blohm
    org.springframework.security:spring-security-core,\
232
    org.springframework.security:spring-security-web,\
233
    org.springframework.security:spring-security-config,\
234
    org.springframework.security:spring-security-aspects
235
    org.springframework:spring-aspects,\
236
    org.springframework:spring-context.support
237 51 Henning Blohm
238
#
239
# enables the processing of @Secured annotations in the implementation
240
#
241
aspectj.privateAspectPathByClass=\
242
	org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect
243
	
244 50 Henning Blohm
245
java.compile.order=java,spring_aspectj
246 51 Henning Blohm
</code></pre>
247
248
See also 
249 1 Henning Blohm
* "AspectJCompiler":http://www.z2-environment.net/javadoc/com.zfabrik.springframework!2Fjava/impl/com/zfabrik/impl/springframework/AspectJCompiler.html
250
* [[sample-spring-basic]] that also contains a Spring Security part.
251
252
253
h3. More important things to know about Spring with AspectJ
254
255
As always, there is some important pitfalls to watch out for. The Spring AspectJ integration roughly works as follows: 
256
257
# When an application context is loaded that has &lt;context:spring-configured /&gt; and the Spring aspect classes are on the classpath (i.e. can be found by the class loader of the application context), then the current application context will be set as a static class variable of one Spring aspect implementation class.
258
# Later, when a configurable object is being instantiated, the woven-in code will look for that static class variable to determine the application context to take configuration from.
259
260
This has a few dramatic consequences:
261
262
* If you would have two application contexts seeing the same static class variable they would override each other and hence you essentially lose control over what configuration is effective.
263
* Hence you should not using Spring AspectJ configuration in API types, as anyone referring to your API would not be able to repeat the trick.
264
265
That's why: *Only use Spring AspectJ in implementations, i.e. under src.impl or src.test*
266
267
h2. Using a parent application context in a Web application application context
268
269
Sometimes, later, when you find that your module has a web app but in addition you want to expose services, from the very same module, i.e. when you have spring configured objects in the web app but also a classpath defined application context that should serve as a _parent application context_ to the one of the web app (admittedly an advanced case), then you will find that that is slightly tricky to achieve (see e.g. http://blog.springsource.org/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/). 
270
271
The class *com.zfabrik.springframework.web.ComponentParentContextContextLoaderListener* is a drop-in replacement for Spring's ContextLoaderListener implementation that simplifies that use-case as explained in the "javadoc":http://www.z2-environment.net/javadoc/com.zfabrik.springframework.web!2Fjava/api/com/zfabrik/springframework/web/ComponentParentContextContextLoaderListener.html.
272 51 Henning Blohm
273 60 Henning Blohm
h2. Using Spring Context Support
274
275
Like the Spring Aspect, but because of dangling imports, the module *org.springframework:spring-context-support* is not meant to be referenced but to be _included_.
276
Including a Java component means that it's resources (class files, jars,...) will be copied into the including scope rather than referenced via class loader delegation.
277
278
The difference is that in that case, all the includer sees is also to be seen by the types in the included component. And that is exactly what spring-context is about: It holds adapter classes that have dangling dependencies (see below) on other prominent libraries, that are _connected_ when included ("assembled") in a _fulfilling_ context. Say for example we are talking about the Lucene search engine library. If your Java component references the Lucene libraries (which are not included with Z2 by default), and say you want to use the Spring adapter types, then include spring-context by adding (i.e. customizing correspondingly) the private include:
279
280
<pre><code class="python">
281
java.privateIncludes=\
282
   org.springframework:spring-context-support
283
</code></pre>
284
285
Typically it makes most sense to only use _private includes_. If you include into the API, which is possible, other modules that reference your API will find the included types
286
of your API with preference of their includes (as part of the parent-first delegation principle). So, they may not be able to repeat the same include pattern described above. 
287
288 50 Henning Blohm
h2. Advanced notes
289
290
As may have leaked through above already, some features of the Spring framework have slightly non-trivial prerequisites. In general these require that Spring provided libraries are used within the context of other Java components - as for context.support above - and that requires some explanation:
291
292 28 Henning Blohm
At runtime, Java components in Z2 have two class loader instances. One for the API definitions of the component, the other for the implementation definitions of the component. The latter is not visible to any referencing component, while the former is. Visibility is achieved by class loader delegation. That is, the class loaders of a referencing Java component will first delegate to the API class loader of the referenced component when looking for a type before checking their own resources. 
293
294 1 Henning Blohm
The delegation sequence is always strictly along the references. 
295 29 Henning Blohm
296 1 Henning Blohm
When we use the term shared library or shared Java component, we are referring to a Java component that can be referenced by others to provide some functionality. At runtime, the types of that Java component are loaded exactly once into the VM's memory. As a side-effect, static class members for example will be shared amongst all usages.
297 29 Henning Blohm
298 55 Henning Blohm
The alternative to sharing a Java component is to “include” a Java component. When a Java component references a component of type *com.zfabrik.files* or *com.zfabrik.java*, libraries and class files of the referenced component will be copied into the referencing component (depending on the reference either into the API or the implementation part). In that case, the types provided by the files component are used in the context of there referencing component and may be loaded several times.
299
300
Considering Spring there are two cases that mandate a non-shared use of libraries.
301
302
h3. Dangling Imports
303
304
Some Spring libraries provide integration of Spring with a variety of third-party libraries. When those libraries were compiled, all those third-party libraries were present on the compilation class path. Java's late linking paradigm allows to use those libraries without the presence of the third-party libraries as long as visibility of those types is not necessary yet.
305
One example of such a library is the context support Spring module. See above for more details.
306
307
h3. Static Members Holding Singletons
308
309
Another reason that mandates in context use is module specific static initialization. In other words there is a class that holds static, class-level data that is specific to the using context.
310
One example of such is the Spring AspectJ context that points to its underlying application context by a class variable. As a consequence, sharing these classes between modules with different application context would lead to confusions about what application context is used during the application of the Spring aspect. That is why the Spring AspectJ library should always be included by a private reference, and the implementation should use only one application context as far as AspectJ configuration is concerned.
311 1 Henning Blohm
312 60 Henning Blohm
h3. Spring stuff that requires includes
313 55 Henning Blohm
314 60 Henning Blohm
Several Spring use cases require the use of includes. Among these are in any case:
315 55 Henning Blohm
316
|_. Use case|_. What to private-include|_.Why|
317 56 Henning Blohm
|Spring context support|org.springframework:spring-context-support|Dangling imports in spring lib|
318 55 Henning Blohm
|Spring AspectJ|org.springframework:spring-aspects|Class loader bound application context (must be kept on scope - see below)|
319 56 Henning Blohm
|Spring Security|org.springframework:spring-security-{config,core,web,...}|Dangling imports in spring lib|
320 61 Henning Blohm
321
Depending on your specific constructions, you may need to import (rather than reference) other Spring libraries as well. For example in [[Sample-springds-hibernate]] it is necessary to include @org.springframework:spring-orm@ as (in that scenario) classes in spring-orm were required that directly depend on the Hibernate ORM implementation. The way, the Spring-add-on was constructed you should be able to solve these constructions without ripping the add-on apart.