Project

General

Profile

Sample-spring-basic » History » Version 25

Henning Blohm, 10.09.2015 15:27

1 8 Henning Blohm
h1. A basic Spring with Z2 modularity sample
2 2 Henning Blohm
3
The sample contained in the repository "z2-samples.spring-basic":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic is a clean room example on how to use the Spring integration features described in [[how_to_spring]].
4
5 25 Henning Blohm
You need is a JDK 6 or JDK 7 distribution as described in [[Step_2_-_Install_and_run_in_5_minutes]].
6
7
*NOTE:* All versions less than 3 will not run with Java 8. You need to use Java 7 instead!
8
9 10 Henning Blohm
There is no further pre-requisite to running this sample, and you may proceed as described in [[How to run a sample]]. Here's the really fast version:
10
11 11 Henning Blohm
<pre><code class="ruby">
12 10 Henning Blohm
mkdir install
13
cd install 
14
git clone -b master http://git.z2-environment.net/z2-base.core
15
git clone -b master http://git.z2-environment.net/z2-samples.spring-basic
16
17 11 Henning Blohm
# on Linux / Mac OS:
18 10 Henning Blohm
cd z2-base.core/run/bin
19
./gui.sh
20
21
# on Windows:
22 12 Henning Blohm
cd z2-base.core\run\bin
23 10 Henning Blohm
gui.bat
24
</code></pre>
25
26 24 Henning Blohm
*Notes:*
27
28
* If you run into read timeouts due to weak internet connection, simply keep repeating to start z2.
29
* If you are located behind an internet proxy, please check [[How_to_proxy_settings]] on how to configure your installation.
30
31
32 15 Henning Blohm
If you want to inspect the code using Eclipse, please create a workspace in install (i.e. *install/workspace*) and import the Git repositories and projects (see also [[Step_3_-_First_steps_with_Z2_on_Git|First steps]]).
33 2 Henning Blohm
34 16 Henning Blohm
There are three modules contained in this sample. For the moment only consider the following two:
35 2 Henning Blohm
36
h2. com.zfabrik.samples.spring-basic.services
37
38 6 Henning Blohm
This module has a classpath defined "applicationContext":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.services/java/src.impl/META-INF/applicationContext.xml and exposes an annotation defined bean "ComputationServiceImpl":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.services/java/src.impl/com/zfabrik/samples/impl/services/ComputationServiceImpl.java bean from it as a service to be consumed from another module: The *computations* bean.
39 2 Henning Blohm
40 17 Henning Blohm
The application context enables discovery of Spring beans that are marked by annotations such as @Service, @Component, @Repository:
41
42
<pre><code class="xml">
43
<beans ...>
44
	<!-- Turn on annotation based config -->
45
	<context:annotation-config/>
46
	<!-- Turn on auto discovery -->
47
	<context:component-scan base-package="com.zfabrik.samples.impl"/>
48
</beans>
49
</code></pre>
50
51
The *computations" bean implementation implements the interface "IComputationService":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.services/java/src.api/com/zfabrik/samples/services/IComputationService.java and is itself not visible to consumers. It's structure is roughly like this:
52
53
<pre><code class="java">
54
@Service("computations")
55
public class ComputationServiceImpl implements IComputationService {
56
57
...
58
59
}
60
</code></pre>
61
62
The *computations* bean is exposed via the Z2 component "com.zfabrik.samples.spring-basic.services/computations":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.services/computations.properties:
63
64
<pre><code class="ruby">
65
com.zfabrik.component.type=org.springframework.bean
66
67
#
68
# the context that defines the bean (more than one
69
# bean can be exposed like this)
70
#
71
bean.context=com.zfabrik.samples.spring-basic.services/applicationContext
72
73
#
74
# the bean name
75
#
76
bean.name=computations
77
</code></pre>
78
79
Note that the Z2 Bean component names its application context. At runtime this means that an attempt to retrieve the bean will make sure the application context is loaded - and not any earlier.
80
81 4 Henning Blohm
h2. com.zfabrik.samples.spring-basic.frontend
82 1 Henning Blohm
83 17 Henning Blohm
This module has a Web application with an application context defined in "WEB-INF/applicationContext":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.frontend/web/WebContent/WEB-INF/applicationContext.xml. It uses Spring AspectJ based annotation driven configuration to inject dependencies into instances of "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.
84 1 Henning Blohm
85 17 Henning Blohm
Note the Java component descriptor that, apart from referencing the service module, holds the minimum declaration to make sure of Spring with AspectJ supported, compile-time-woven annotation based configuration:
86
87
<pre><code class="ruby">
88
com.zfabrik.component.type=com.zfabrik.java
89
90
java.privateReferences=\
91 22 Henning Blohm
	com.zfabrik.springframework.web,\
92
	org.springframework.tx,\
93 1 Henning Blohm
	org.springframework.orm,\
94
	com.zfabrik.samples.spring-basic.services
95 17 Henning Blohm
96
java.privateIncludes=\
97 22 Henning Blohm
	org.springframework.security:spring-security-core,\
98
	org.springframework:spring-aspects
99 17 Henning Blohm
100
java.compile.order=java,spring_aspectj
101
</code></pre>
102
103
104
It's "application context":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.frontend/web/WebContent/WEB-INF/applicationContext.xml imports the *computations* service from the other module above and enables the use of Spring configuration (note: Unlike above it does not enable discovery of Spring beans):
105
106
<pre><code class="xml">
107
<beans ... >
108
	<!-- turn on @Configurable support -->
109
	<context:spring-configured/>
110
	<!-- Turn on annotation based config -->
111
	<context:annotation-config/>
112
 	<!-- application config: Bind the bean at samples.spring.simplemodules.services/computations --> 
113
	<bean id="computations" class="com.zfabrik.springframework.ComponentFactoryBean">
114
		<property name="componentName" value="com.zfabrik.samples.spring-basic.services/computations"/>
115
		<property name="className" value="com.zfabrik.samples.services.IComputationService"/>
116
	</bean>
117
</beans>
118
</code></pre>
119 7 Henning Blohm
120 9 Henning Blohm
h2. Finally
121
122 19 Henning Blohm
Open a browser and navigate to http://localhost:8080/spring-basic to verify you get this:
123 9 Henning Blohm
124 1 Henning Blohm
!frontend.png!
125 16 Henning Blohm
126
h1. An extended Spring with Z2 modularity and some Spring Security sample
127
128
The third module *com.zfabrik.samples.spring-basic.secured* contained in the sample repository implements a very similar basic frontend to the one above but illustrating in addition:
129
130
* How to use Spring Security to secure the access to a Web application
131
* How to use Spring Security to secure methods of a bean
132
* How to use Spring Security with Spring AspectJ weaving
133
134 18 Henning Blohm
More specifically, the contained Web application knows of two users *"user"* (password "user") and *"admin"* (password "admin") that have roles @ROLE_USER@ or @ROLE_USER@ and @ROLE_ADMIN@ respectively.
135
136
The controller servlet delegates operations to a _session facade_ implemented by the class "SomeFacadeImpl":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.secured/java/src.impl/com/zfabrik/samples/impl/facades/SomeFacadeImpl.java that offers two methods, one requiring @ROLE_USER@, one requiring @ROLE_ADMIN@.
137
138
But let's rather have a step-by-step overview: The Java component declaration "com.zfabrik.samples.spring-basic.secured/java":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.secured/java/z.properties, as compared to the one of the other frontend module has some noteworthy additions:
139
140
<pre><code class="ruby">
141
com.zfabrik.component.type=com.zfabrik.java
142
143
java.privateReferences=\
144 23 Henning Blohm
	com.zfabrik.samples.spring-basic.services,\
145
	org.springframework.tx,\
146 1 Henning Blohm
	org.springframework.orm,\
147 23 Henning Blohm
	com.zfabrik.springframework.web
148 18 Henning Blohm
149
java.privateIncludes=\
150 23 Henning Blohm
	org.springframework:spring-aspects,\
151
	org.springframework.security:spring-security-core,\
152
	org.springframework.security:spring-security-web,\
153
	org.springframework.security:spring-security-config,\
154
	org.springframework.security:spring-security-aspects
155 18 Henning Blohm
156
#
157
# this enables the processing of @Secured annotations
158
#
159
aspectj.privateAspectPathByClass=\
160
	org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect
161
	
162
java.compile.order=java,spring_aspectj
163
</code></pre>
164
165
One the one it references the Spring Security module and it includes some Spring Security elements (that unfortunately must be included). Notably the support for Web apps, the *config* support, and finally the *aspect*, which is the pre-requisite for AspectJ support with Spring Security. 
166
167
We prefer AspectJ compile-time weaving over Spring AOP as it is much more consistent (non-proxy-based AOP, see also [[how_to_spring]] and elsewhere) and, as the compilation part is automatic with Z2, no extra burden to configure. 
168
169
However, to let the Spring AspectJ compiler, supported by Z2 know about the handling of Spring Security annotations used in the implementation, the corresponding _Aspect Implementation_ must be indicated. Hence the additional property "aspectj.privateAspectPathByClass". See also "AspectJCompiler":http://www.z2-environment.net/javadoc/com.zfabrik.springframework!2Fjava/impl/com/zfabrik/impl/springframework/AspectJCompiler.html for more details.
170
171
Fortunately this was the hardest part of our configuration tour. 
172
173
The Web apps "application context":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.secured/web/WebContent/WEB-INF/applicationContext.xml has a lot of similarities to the one of the other frontend but adds some Spring Security related configuration:
174
175
176
<pre><code class="xml">
177
...
178
179
	<!-- web security config: require basic authentication, hard-coded users "user" and "admin" -->
180
	<security:http auto-config='true' disable-url-rewriting="true">
181
		<security:intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER" />
182
		<security:http-basic />
183
	</security:http>
184
185
	<security:authentication-manager>
186
		<security:authentication-provider>
187
			<security:user-service>
188
				<security:user name="admin" password="admin" authorities="ROLE_ADMIN,ROLE_USER" />
189
				<security:user name="user" password="user" authorities="ROLE_USER" />
190
			</security:user-service>
191
		</security:authentication-provider>
192
	</security:authentication-manager>
193
194
	<!-- method security config (in this case, only Secured annotations enabled)-->
195
	<security:global-method-security
196
		secured-annotations="enabled"
197
		mode="aspectj"
198
	/>
199
200
...
201
</code></pre>
202
203
Having users and passwords declared in the application context is is a sacrifice due to the sample nature. Other than that these declarations say that 
204
205
# the Web app uses Basic Authentication (being simpler than a form-based login for the sample), 
206
# that all requests require either @ROLE_USER@ or @ROLE_ADMIN@, and 
207
# that it makes use of _Method Security_, expecting the support of @Secured annotations with AspectJ weaving.
208
209
The controller servlet ("ControllerServlet":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.secured/java/src.impl/com/zfabrik/samples/impl/frontend/ControllerServlet.java) delegates all calls to the facade implementation "SomeFacadeImpl":https://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-basic/revisions/master/entry/com.zfabrik.samples.spring-basic.secured/java/src.impl/com/zfabrik/samples/impl/facades/SomeFacadeImpl.java that has secured methods:
210
211
<pre><code class="java">
212
@Component
213
public class SomeFacadeImpl {
214
	private final static Logger LOG = Logger.getLogger(SomeFacadeImpl.class.getName());
215
	
216
	public SomeFacadeImpl() {
217
		LOG.info("Init of "+this);
218
	}
219
220
	@Autowired
221
	private IComputationService computations;
222
223
	@Secured("ROLE_USER")
224
	public String doSomethingWithAString(String in) {
225
		return computations.doSomethingWithAString(in);
226
	}
227
	
228
	@Secured("ROLE_ADMIN")
229
	public String doSomethingThatRequiresAdmin() {
230
		return "Yes, you can!";
231
	}	
232
}
233
</code></pre>
234
235
It does use the re-use service *computations* from the other module and gets it injected as above.
236
237 20 Henning Blohm
Now, if you open a Web browser at http://localhost:8080/spring-basic-secured you will first be asked to log in (best try "user" with password "user" first) and next offered the following options:
238 18 Henning Blohm
239
!secured.png!
240
241 21 Henning Blohm
Pressing the button beneath "Try as admin" should give you an "Access denied" response, if you did not log on with the "admin" user, while it should give some affirmative response in case you did not log with admin permissions.