VRaptor

What are components?

Components are object instances that your application need to execute tasks or to keep state in different situations.

Common examples of components are DAOs and e-mail senders. The best practices suggest you should always create interfaces for your components to implement. This makes your code much easier to unit test.

The following example shows a VRaptor-managed component:

@RequestScoped
public class CustomerDao {

    private final Session session;

    /**
     * @deprecated CDI eyes only
     */
    protected CustomerDao() {
        this(null);
    }

    @Inject
    public CustomerDao(Session session) {
        this.session = session;
    }

    public void add(Customer customer) {
        session.save(customer);
    }
}

Every component from VRaptor is managed by CDI (Context Dependency Injection) from Java EE 7. Therefore, all capabilities implemented by CDI are present in VRaptor.

For more information about CDI, check the Java EE 7 docs.

To make your components available in the view you can use the @Named annotation. In the next example you can see how to make the class User available in the view:

@SessionScoped
@Named("user")
public class User {
    private final String name;

    private String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;
    }
}

And in the view the object will be available as user variable:

<p>Welcome, ${user.name}.</p>

Scopes

It’s important to notice that components has its own lifecycle. The default behavior is that a new instance will be built everytime it needs to be injected and disposed together with the object in which it was injected (the dependent scope as we will see later).

The following example shows a class to hold email configurations of an application. Any compoment of the application could receive this object to read email configurations (notice that this just an simple example, the recommended way to implement it would be using environment support of VRaptor).

This component has application scope, so will be instantiated just once per application lifecycle.

@ApplicationScoped
public class EmailConfiguration {
    private final String host = "smtp.bazinga.com"
    private final String user = "foo";
    private final String password = "bar";

    public Session getHost() {
        return host;
    }

    public Session getUser() {
        return user;
    }

    public Session getPassword() {
        return password;
    }

}

The implemented scopes are:

@ApplicationScoped the component is a singleton, just one for the entire application.
@SessionScoped the component is the same during the http session of the container.
@ConversationScoped the component instance is kept during a conversation.
@RequestScoped the component is the same during a request.
@Dependent the component is instanciated whenever it is requested.

For more information about scopes, check the Java EE 7 documentation about scopes.

Building components

Sometimes you need to inject a dependency that isn’t from your application, for example a Hibernate Session or a JPA EnitityManager.

To do this, you need to create a method annotated with @Produces:

@RequestScoped
public class SessionCreator {

    @Inject
    private SessionFactory sessionFactory;

    @Produces
    @RequestScoped
    public Session getSession() {
        return sessionFactory.openSession();
    }

    public void close(@Disposes Session session) {
        if (session.isOpen()) {
            session.close();
        }
    }
}

See that we are injecting and SessionFactory, so we would also need a producer of SessionFactory:

@ApplicationScoped
public class SessionFactoryCreator {

    private SessionFactory factory;

    @PostConstruct
    public void init() {
        this.factory = new AnnotationConfiguration().configure().buildSessionFactory();
    }

    @Produces
    public SessionFactory getSession() {
        return factory;
    }

    @PreDestroy
    public void close() {
        if (!factory.isClosed()) {
            factory.close();
        }
    }
}

You can use the listeners @PostConstruct, @PreDestroy and @Disposes to get notified about the lifecycle of the component and control the allocation and deallocation of resources.

In the previous example, we annotated the method init() that will be executed right after the instatiation of the class. The method close() will be invoked before the DI container dispose this object.

You can annotate the methods of your VRaptor’s components with all of the mentioned annotations.

Dependency Injection

VRaptor uses CDI to instantiate components and controllers. Thus, the previous examples (CustomerDao and SessionCreator) enable that any controller or component receive a CustomerDao injected in its constructor. To do so, CDI forces us to implement a default constructor, for example:

@Controller
public class CustomerController {

    private final CustomerDao dao;

    /**
     * @deprecated CDI eyes only
     */
    protected CustomerController() {
        this(null);
    }

    @Inject
    public CustomerController(CustomerDao dao) {
        this.dao = dao;
    }

    @Post
    public void add(Customer customer) {
        this.dao.add(customer);
    }
}

Injecting Java EE resources

Injection also works for all Java EE components if you are deploying your application in an Application Server. All annotations like @Resource, @EJB, @PersistenceContext, @PersistenceUnit and @WebServiceRef works fine when you using injection by field.

In the code below we are injecting an EJB and an SessionContext in your controller:

@Controller
public class CustomerController {

    @EJB
    private CustomerBean customerBean;

    @Resource
    private SessionContext context;

}

But if you want to use constructor injection, only EJB resources are available to injection using @Inject annotation. All resources annotated with @Resource and others needs a producer. In the example below we create a producer to make SessionContext available to use with constructor injection:

@Dependent
public class Resources {
 
    @Produces
    @Resource(mappedName = "java:comp/EJBContext")
    protected SessionContext sessionContext;
}

And now we can inject the SessionContext in our controller. See the code below:

@Controller
public class CustomerController {

    private CustomerBean customerBean;
    private SessionContext context;

    /**
     * @deprecated CDI eyes only
     */
    protected CustomerController() {
        this(null, null);
    }

    @Inject
    public CustomerController(CustomerBean customerBean, SessionContext context) {
        this.customerBean = customerBean;
        this.context = context;
    }

}

If you are not using our vraptor-jpa plugin, and you want to use EntityManager provided by the Appplication Server, you need to create a producer for EntityManager like this example:

@Dependent
public class Resources {

    // your other producers

    @Produces
    @PersistenceContext
    protected EntityManager em;
}

Observing and firing events

You can fire events and handle them with the @Observes annotation.

If you need, for example, log an message during the bootstrap of your application, you can observe the VRaptorInitialized event, like this:

@ApplicationScoped
public class PrintLog {

    public void observesBootstrap(@Observes VRaptorInitialized event) {
        System.out.println("My application is UP");
    }
}

See the events documentation page for more information about VRaptor’s events.

Overriding components

Most of VRaptor’s conventions and behaviors can be customized. It’s simple to customize something: all you need to do is extend an internal class from VRaptor and annotate it with @Specializes. After doing this, the framework will use the custom implementation instead of the default one.

In case you need to implement an internal interface, you need to annotate the implementation with @Priority, so VRaptor will use your implementation instead of its own:

@Priority(Interceptor.Priority.LIBRARY_BEFORE + 10)

Customizing VRaptor

Let’s see how we can customize some of the default behaviors of VRaptor.

Customizing the default view

If you need to change the default rendered view, or change the place where it’ll be look for, you’ll only need to create the following class:

@Specializes
public class CustomPathResolver extends DefaultPathResolver {

    /**
     * @deprecated CDI eyes only
     */
    protected CustomPathResolver() {
        this(null);
    }

    @Inject
    public CustomPathResolver(FormatResolver resolver) {
        super(resolver);
    }

    @Override
    protected String getPrefix() {
        return "/root/directory/";
    }

    @Override
    protected String getExtension() {
        return "ftl"; // ou any other extension
    }

    @Override
    protected String extractControllerFromName(String baseName) {
        return //your convention here
               
    }
}

You can implement your own convention, for instance:

ex.: If you want to redirect UserController to userResource instead of user ex.2: If you override the convention for Controllers name to XXXResource and still want to redirect to user and not to userResource

If you need a more complex convention, just implement the PathResolver interface.

Changing default URI

The default URI for CustomerController.list() is /customer/list, i.e, controller_name/method_name. If you want to override this convention, you can create a class like:

@Specializes @ApplicationScoped
public class MyRoutesParser extends PathAnnotationRoutesParser {
    //delegated constructors 
    protected String extractControllerNameFrom(Class<?> type) {
        return //your convention here
    }

    protected String defaultUriFor(String controllerName, String methodName) {
        return //your convention here
    }
}

If you need to change the convention to both default and annotated URI, you can create a class overriding the convention. The example below will make all URIs accessible with /prefix prefix.

So, if the route is /index, the URI will be /prefix/index.

@Specializes @ApplicationScoped
public class PrefixedRoutesParser extends PathAnnotationRoutesParser {
    //delegated constructors 

    @Override
    protected String[] getURIsFor(Method javaMethod, Class<?> type) {
        String[] uris = super.getURIsFor(javaMethod, type);
        for (int i = 0; i < uris.length; i++) {
            uris[i] = "/prefix" + uris[i];
        }
        return uris;
    }
}

If you need a more complex convention, just implement the RoutesParser interface.

Changing the application character encoding

For using an arbitrary character encoding on all your requests and responses, avoiding encoding inconsistencies, you can set this parameter on your web.xml.

<context-param>
    <param-name>br.com.caelum.vraptor.encoding</param-name>
    <param-value>UTF-8</param-value>
</context-param>

This way all of your pages and form data will use the UTF-8.

Instantiating only request present parameters

The default behavior is that all objects that you ask in your controller methods will be instantiated even if these parameters are not present in the request. You can change this behavior in a very simple way, overriding the VRaptorInstantiator class:

@Specializes
public class NullVRaptorInstantiator extends VRaptorInstantiator {

    //delegate constructor

    @Override
    public boolean useNullForMissingParameters() {
        return true;
    }
}

Thus, when the data of an object are not present in the request, you will receive a null parameter instead of an empty instance.

Using the Try class

You can use the class Try from the public API of VRaptor to handle exceptions more easily.

With this class, you can specify the code that might throw exceptions with the run method:

Try try = Try.run(() -> aDangerousMethod());
if (try.failed()) {
    Exception e = try.getException();
    handleError(e);
}
handleResult(try.result());

This class is really useful to compose several computations that can throw exceptions.