Saturday, October 29, 2011

100% Vaadin and Spring integration without hacks

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.

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.
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.

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:
<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.

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:
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

Wednesday, June 2, 2010

Fast and easy java bean mapping

Java Bean mapping is essential part of many applications. Mapping is often used to serialize Hibernate/JPA/JDO objects, to filter data, to save space/bandwidth when full object data is not needed.
When you are working on GWT application there are two common ways of mapping domain objects between front-end and back-end. One of them is to use same class on both client and server side and use some framework like Gilead to maintain session-related state of object.
Another way is to use data transfer objects on client side. Advantage of such approach are reduced bandwidth usage (you can transfer only data that you are really need in current operation and do not transfer unrelated to current operation data), increased security (you can expose only fields that are really needed to current operation), reduced memory footprint (no need to save session state data on server).
Popular bean mapping frameworks are including Dozer or Apache BeanUtils but all of these frameworks are intensively using reflections to perform mapping operations. Such approach is much slower than mapping performed "by hands", e.g. when you write code like this one:
EntityDto dto = new EntityDto();
dto.setId(entity.getId());
dto.setName(entity.getName());
...
I need solution that works as fast as "by hands" mapping but i am too lazy to write hundreds of lines of routine mapping code.
So i've started small project that generates mapping classes that are as fast as hand-written ones.
Project is located at Google Code: Bean Mapper and it is very easy to use.
To use it you should perform 3 easy steps:
  1. Define mapper interface and annotate methods that should be generated with @Mapper annotation:
    public interface EntityMapper {
       @Mapper
        List<DestinationEntity> map(List<SourceEntity> source);
    }
  2. Obtain implementation of mapper class through factory:
    EntityMapper mapper = (EntityMapper) MapperFactory.getInstance(EntityMapper.class);
    
  3. Use your mapper class:
    List<DestinationEntity> = mapper.map(someSource);
    

Methods that are being generated are as fast as hand-coded. For example if you have 2 classes like these:
public class ClassA {
    int fileld1;
    boolean field2;
    String field3;
    List<ClassA> children;
    //getters and setters
}
public class ClassA {
    String fileld1;
    String field2;
    String field3;
    List<ClassB> children;
    //getters and setters
}
the code being generated for mapping ClassA -> ClassB will look like this:
public ClassB map(ClassA param) {
    ClassB target = new ClassB();
    target.setField1(String.valueOf(param.getField1()));
    target.setField2(String.valueOf(param.getField2()));
    target.setField1(param.getField3());
    if (param.getChildren() != null) {
        target.setChildren(new ArrayList());
        for (ClassA child : param.getChildren()) {
            target.getChildren().add(map(child));
        }
    }
    return target;
}
Actually there will be little more code to properly handle null values, loop dependencies etc. but it will be code that is not using any Reflections overhead and it works several times faster than dynamic mapping frameworks. In some cases it works 100-200 times faster.

Project development is frozen for some time now but it looks stable and I am using it on some of my home projects without any problems.

Monday, May 3, 2010

Dynamic DAO generation

Almost any developer working on enterprise projects spend reasonable amount of time writing DAO classes and tests for them.
Most of this code is trivial, especially in case of ORM frameworks, and I think that it should be generated instead of hand-writing. Why should I waste my time writing routine code, writing tests for it and leaving space for errors despite of tests?
So I wrote very small framework (not actually framework, just a few classes) that generates DAO classes for Hibernate framework.
You just write interfaces for DAO, annotate them and framework do all the routine work for you.
Code being generated is usually as effective as hand-written one and [most] of bugs are already fixed.

Here how DAO interface looks:
public interface EntityDao extends DynamicDao<Entity, Long> {
        List<SomeEntity> getPaginatedFilteredByCriteriaOrderedByCriteria(
            @Pagination.Paginate Pagination pagination,
            @Restriction.Restrict Restriction restriction,
            @Ordering.Criteria Ordering ordering
    );
}

Here how it can be used:
EntityDao entityDao = (EntityDao) DaoFactory.getInstance(EntityDao.class, Entity.class, sessionFactory);
List<Entity> entities = entityDao.getPaginatedFilteredByCriteriaOrderedByCriteria(
    new Pagination(6, 7), 
    Restriction.or(
        Restriction.ilike("name", "vaLue 1"),
        Restriction.like("name", "value 2")),
    new Ordering("name", Ordering.Direction.DESC).Order("id"));

And this is example of actual code auto-generated for interface method above:
public List getPaginatedFilteredByCriteriaOrderedByCriteria(
   Pagination p0, Restriction p1, Ordering p2) {
    Session session = ThreadLocalSessionFactory.getSession();
    Criteria criteria = session.createCriteria(entityClass);
    Restriction restrictionValue = p1;
    Criterion criterion = getCriterion(restrictionValue);
    if (criterion != null) {
        criteria.add(criterion);
    }
    Ordering sortingCriteriaValue = p2;
    while (sortingCriteriaValue != null) {
        if (sortingCriteriaValue.getDirection() == Ordering.Direction.ASC) {
            criteria.addOrder(Order.asc(sortingCriteriaValue.getField()));
        } else if (sortingCriteriaValue.getDirection() == Ordering.Direction.DESC) {
            criteria.addOrder(Order.desc(sortingCriteriaValue.getField()));
        }
        sortingCriteriaValue = sortingCriteriaValue.getChild();
    }
    if (p0 != null) {
        criteria.setFirstResult(p0.getFirstResult());
        criteria.setMaxResults(p0.getMaxResults());
    }
    return criteria.list();
}

Generated DAO classes can be easily exposed as Spring beans.

More information, docs and examples on project's site on Google Code: http://code.google.com/p/dyndao/

The framework is not finished yet (code is not well documented, there are possibly bugs left etc.) and I have no time for it right now but I hope it will look as a real project in near future.
It looking stable and I know at least one project in production stage that is using it.
Anyone interested in project development are welcome.

Monday, April 19, 2010

Spring-managed GWT Remote Service: exposing Spring bean as GWT RPC

Update: there are easier and much easier ways of doing this.
I want to publish simple solution to expose Spring Bean as Google Web Toolkit Remote Service.
There are some solutions around but they are hard to configure, heavy-weight and often do not provide functionality required to use AOP-based annotations on service methods (like Spring Security @Secured) but I prefer minimal XML configuration (In this example there are only few lines of XML), annotation-driven configuration and functionality without any limitations.

So it is needed to create

a) Spring-managed servlet that will handle RPC calls
b) Remote Service common logic implementation
c) Simple GWT RPC Example

Spring servlet to handle RPC calls

package com.example.server.service;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Component("gwt-request-handler")
public class RemoteServiceHandler implements HttpRequestHandler, ApplicationContextAware {
    private ApplicationContext applicationContext;

    public void handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
        String requestPath = httpServletRequest.getServletPath();
        @SuppressWarnings({"unchecked"})
        Map<String, RemoteService> services = applicationContext.getBeansOfType(RemoteService.class);
        RemoteService service = null;
        for (String key : services.keySet()) {
            if (requestPath.endsWith(key)) {
                if (service != null) {
                    throw new IllegalStateException("More than one GWT RPC service bean matches request: " + requestPath);
                } else {
                    service = services.get(key);
                }
            }
        }
        if (service == null) {
            String availableServlets = "";
            for (String key : services.keySet()) {
                availableServlets += key + " -> " + services.get(key).getClass().getName() + "\n";
            }
            throw new IllegalStateException("Cannot find GWT RPC service bean for request: " + requestPath + "\nMake sure that service implementation extends RemoteServiceImpl instead of GWT RemoteServiceServlet\nList of available beans:\n" + availableServlets);
        }
        service.doPost(service, httpServletRequest, httpServletResponse);
    }

    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }
}

it should be configured as servlet in web.xml file:

<servlet>
        <servlet-name>gwt-request-handler</servlet-name>
        <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>gwt-request-handler</servlet-name>
        <url-pattern>*.gwtrpc</url-pattern>
    </servlet-mapping>

Spring HttpRequestHandlerServlet will try to locate bean with name same as servlet name and use it to handle all requests matching specified url-pattern.

Remote Service common implementation


This class will take care of ServletContext because these beans are not actually servlets but GWT requires ServletContext to work.
Also it invokes remote methods in a way that allows AOP annotations to work.
Interface is needed to correct work with AOP based annotations, like @Transactional or @Secured

package com.example.server.service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface RemoteService {
    void doPost(RemoteService service, HttpServletRequest request, HttpServletResponse response);

}

package com.example.server.service;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class RemoteServiceImpl extends RemoteServiceServlet implements RemoteService {
    private RemoteService service = null;

    public void doPost(RemoteService service, HttpServletRequest request, HttpServletResponse response) {
        this.service = service;
        doPost(request, response);
    }

    @Override
    public ServletContext getServletContext() {
        ServletContext context;
        try {
            context = super.getServletContext();
        } catch (Exception e) {
            context = getThreadLocalRequest().getSession().getServletContext();
        }
        return context;
    }

    @Override
    public String processCall(final String payload) throws SerializationException {
        final RPCRequest request = RPC.decodeRequest(payload, this.getClass(), this);
        try {
            Object result = request.getMethod().invoke(service, request.getParameters());
            return RPC.encodeResponseForSuccess(request.getMethod(), result, request.getSerializationPolicy());
        } catch (IllegalAccessException e) {
            return RPC.encodeResponseForFailure(request.getMethod(), e, request.getSerializationPolicy());
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            return RPC.encodeResponseForFailure(request.getMethod(), cause, request.getSerializationPolicy());
        } catch (IncompatibleRemoteServiceException ex) {
            return RPC.encodeResponseForFailure(null, ex, request.getSerializationPolicy());
        } finally {
            service = null;
        }
    }
}

Simple Remote Service

Here is implementation of very simple remote service managed by Spring.
You can use any AOP annotation and/or other spring features like autowiring without any limitation.
package com.example.client.service;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.google.gwt.core.client.GWT;

@RemoteServiceRelativePath(TestService.URL)
public interface TestService extends RemoteService {
    public static final String URL = "services/TestService.gwtrpc";

    public String hello(String userName);

    public static class Instance {
        private static final TestServiceAsync instance = (TestServiceAsync) GWT.create(TestService.class);

        public static TestServiceAsync get() {
            return instance;
        }
    }
}

package com.example.server.service;

import com.example.client.service.TestService;
import org.springframework.stereotype.Component;

@Component(TestService.URL)
public class TestServiceImpl extends RemoteServiceImpl implements TestService {
    public String hello(String userName) {
        return "Hello " + userName;
    }
}

Spring context configuration


<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:component-scan base-package="com.example.server.service"/>
</beans>