About 6 months ago I've started working on a new project.
Vaadin was chosen as a UI framework for our product. As this project looked very simple it was decided to use very straight-forward application design. Components where instantiated manually, for inter-component communications and passing component references around we used "Application context". Later event bus solution was added for application-wide messaging.
During recent months that project have grown significantly and it became really hard to support it because of well-known tight coupling problem.
Project was refactored to use Spring for injecting dependencies between UI components and managing UI component instantiation that allowed us to get rid of application context and event bus.
A week later I've noticed that it turned out to be a non-trivial solution for some people around.
Here I publishing Address Book example from Book of Vaadin refactored to fully utilize Spring throughout the application including UI layer, inter-component dependencies and component scope management.
This application uses AspectJ but can be easily adapted to work without it.
You can download working application source following the link.
Saturday, October 29, 2011
Thursday, June 2, 2011
GWT and Spring Security integration: as easy as pie
There is very easy way of integrating GWT remote services with Spring Security method level security but I never seen such solution on the internet.
This solution utilizes AOP, and I will use aspectJ for compile-time weaving but you can use spring-aop if there are reasons not to use aspectJ in your project.
Let's start with security exception that will work on GWT client side.
I'm leaving up to you adding reasons why exception is thrown (Not logged in, not authorized, session expired etc.)
Next, create Spring context configuration that will configure Spring Security to use method level security only, without URL filtering because you don't need it in GWT RPC.
I also including here configuration for annotation-driven context and aspectJ configuration.
You can use this in following way:
This solution utilizes AOP, and I will use aspectJ for compile-time weaving but you can use spring-aop if there are reasons not to use aspectJ in your project.
Let's start with security exception that will work on GWT client side.
package com.mm.client; import java.io.Serializable; public class AppSecurityException extends RuntimeException implements Serializable { public AppSecurityException() { super(); } }There are 2 things to note: this exception should be unchecked exception and you should specify it in throws declaration of secured GWT RPC method despite it is unchecked exception.
I'm leaving up to you adding reasons why exception is thrown (Not logged in, not authorized, session expired etc.)
Next, create Spring context configuration that will configure Spring Security to use method level security only, without URL filtering because you don't need it in GWT RPC.
I also including here configuration for annotation-driven context and aspectJ configuration.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <context:annotation-config/> <context:spring-configured/> <context:component-scan base-package="com.mm"/> <security:global-method-security secured-annotations="enabled" mode="aspectj"/> <bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy"> <security:filter-chain-map path-type="ant"> <security:filter-chain pattern="/app/*" filters="securityContextPersistenceFilter"/> </security:filter-chain-map> </bean> <bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> <property name="forceEagerSessionCreation" value="true"/> </bean> </beans>Do not forget to include filter in web.xml
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/app/*</url-pattern> </filter-mapping>Next step is to define marker annotation for secured methods
package com.mm.server; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target(ElementType.METHOD) public @interface GwtMethod { }And last part of setup is to define aspect that will translate Spring Security exception to your app exception:
package com.mm.server; import com.mm.client.AppSecurityException; import org.springframework.security.core.AuthenticationException; public aspect SecurityExceptionAspect { declare precedence:SecurityExceptionAspect,*; private pointcut executionOfGwtMethod(): execution(* *(..)) && @annotation(GwtMethod); Object around(): executionOfGwtMethod() { try { return proceed(); } catch (AuthenticationException e) { throw new AppSecurityException(); } } }That's all.
You can use this in following way:
package com.mm.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.mm.client.AppSecurityException; import com.mm.client.SecurityTestService; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.security.access.annotation.Secured; @Configurable public class SecurityTestServiceImpl extends RemoteServiceServlet implements SecurityTestService { @Override @Secured("ROLE_LOGGED_IN") @GwtMethod public String securedMethod() throws AppSecurityException { return "Ok"; } }And catch it in client code like this:
new AsyncCallback<String>() { @Override public void onFailure(Throwable caught) { if (caught instanceof AppSecurityException) { //Security error, handle it accordingly } else { //Some other error } } @Override public void onSuccess(String result) { // Handle result } }You can download working example here.
Labels:
annotation,
aop,
aspectj,
google,
gwt,
rpc,
security,
servlet,
spring,
spring security
Sunday, May 22, 2011
Spring beans and annotations in servlet with aspectj
Sometimes you have limited set of technologies to use on your project (for example you cannot go beyond already approved technology stack or you have very conservative team lead/manager etc).
In these cases usage of techniques like this or this is a good solution to go.
But i've noticed that lots of people with total freedom of technologies to choose are still using solutions like mentioned before or some self-made variation of these.
I believe that if there is a ready, tested and well-known solution to your problem - you should this solution and not to invent another bicycle.
In case of using Spring in a servlet (GWT RPC or any other) this solution is aspectj.
Here is a short how-to use Spring in a servlet. I will use Maven but you can easily adapt this to what you are using for dependency management and/or build.
First, we need to define required dependencies in POM file:
Afterwards you can simply use @Autowired annotation on servlet fields.
Of course you will need to add some HTTP filter that will translate exceptions to user-readable format but this is out of scope of this article.
In these cases usage of techniques like this or this is a good solution to go.
But i've noticed that lots of people with total freedom of technologies to choose are still using solutions like mentioned before or some self-made variation of these.
I believe that if there is a ready, tested and well-known solution to your problem - you should this solution and not to invent another bicycle.
In case of using Spring in a servlet (GWT RPC or any other) this solution is aspectj.
Here is a short how-to use Spring in a servlet. I will use Maven but you can easily adapt this to what you are using for dependency management and/or build.
First, we need to define required dependencies in POM file:
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>3.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.10</version> </dependency> </dependencies>and add aspectj compiler phase:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> <aspectLibraries> <aspectLibrary> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>Then create Spring config file that will tell Spring to manage classes created outside of Spring context:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <context:spring-configured/> </beans>Last thing you need is to add org.springframework.beans.factory.annotation.Configurable annotation to servlet class.
Afterwards you can simply use @Autowired annotation on servlet fields.
@Configurable public class Servlet extends HttpServlet { @Autowired private Bean bean; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { bean.doSomething(); } }@Transactional annotations should be configured in Spring context XML like following: <tx:annotation-driven mode="aspectj"/>, and the same with @Secured.
Of course you will need to add some HTTP filter that will translate exceptions to user-readable format but this is out of scope of this article.
Labels:
annotation,
aop,
aspectj,
autowiring,
bean,
gwt,
servlet,
spring
Tuesday, February 15, 2011
Simple Spring bean autowiring in GWT servlet
Update: there is easier way of doing this.
Some time ago i've posted a solution to expose Spring bean as GWT remote service.
That solution supports all Spring stuff like AOP annotations, @Transactional, @Secured from Spring security etc.
But it is no a very easy to remember, it is sometimes tricky to support through IDE and all these features are not always needed, especially when you already have business logic layer that implements all security, transaction demarcation and whatever.
So when you need GWT RemoteService servlet just to delegate all the work to some Spring bean following solution comes handy, mainly because it is only a few lines of code long and very easy to remember.
You need to create a parent class for all your GWT servlets that slightly extends RemoteServiceServlet:
Some time ago i've posted a solution to expose Spring bean as GWT remote service.
That solution supports all Spring stuff like AOP annotations, @Transactional, @Secured from Spring security etc.
But it is no a very easy to remember, it is sometimes tricky to support through IDE and all these features are not always needed, especially when you already have business logic layer that implements all security, transaction demarcation and whatever.
So when you need GWT RemoteService servlet just to delegate all the work to some Spring bean following solution comes handy, mainly because it is only a few lines of code long and very easy to remember.
You need to create a parent class for all your GWT servlets that slightly extends RemoteServiceServlet:
public class SpringGwtServlet extends RemoteServiceServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); WebApplicationContextUtils. getRequiredWebApplicationContext(getServletContext()). getAutowireCapableBeanFactory(). autowireBean(this); } }And then implement your services as usual but extend your class instead of default RemoteServiceServlet defining fields for autowired dependencies and marking them with @Autowired annotation.
public class ReportServiceImpl extends SpringGwtServlet implements ReportService { @Autowired private ReportManager reportManager; public Report createReport(long id) { return reportManager.createReport(id); } }Tested with Spring 2.5.6 and 3.0.x
Subscribe to:
Posts (Atom)