2010-07-22

@Named vs. @ManagedBean in JSF 2.0

A lot of people seem to suggest that you should use @Named instead of @ManagedBean in JSF 2.0 (e.g. see @ManagedBean dead on arrival? or this JavaRanch discussion).

However, what I discovered in a painful process is that you must use @ManagedBean when the scope is @ViewScoped, apparently because CDI doesn’t declare a view scope. Thus this is correct:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class DogsBean {
// ...

NOTE: I am using JBoss 6 M3.

2010-07-21

Custom validation with Bean Validation (JSR-303)

In my previous post on Bean Validation I explained how to use built-in constrains. When the standard constraints aren’t enough, you can develop your own.


Custom constraint


Let’s create a custom constraint and have it checked that the first character is an uppercase one.

package me.m1key.jsf.constraints;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = FirstUpperValidator.class)
@Target( { METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface FirstUpper {
 String message() default "{me.m1key.jsf.constraints.FirstUpper.message}";

 Class<?>[] groups() default {};

 Class<? extends Payload>[] payload() default {};
}

  • message - the error message. You can omit curly braces and just hard code it
  • groups - this is for grouping validations (if one group fails - other groups are not checked; here we use the default group)
  • payload - additional type-safe information might be carried here

Now, we need the validator.


Custom validator


package me.m1key.jsf.constraints;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class FirstUpperValidator implements
     ConstraintValidator<FirstUpper, String> {

 @Override
 public void initialize(FirstUpper firstUpper) {
     // See JSR 303 Section 2.4.1 for sample implementation.
 }

 @Override
 public boolean isValid(String value, ConstraintValidatorContext context) {
     if (value == null || value.length() == 0) {
         return true;
     }
     return value.substring(0, 1)
             .equals(value.substring(0, 1).toUpperCase());
 }
}

Nothing special here. Finally, the usage...


The usage


It’s identical as any other constraint.
@NotNull
  @Size(min = 3)
  @FirstUpper
  public String getName() {
      return name;
  }


Summary


I showed you how to write custom constraints and gave a hint about existence and purpose of groups and payloads.

Download source code for this article

Read on

2010-07-20

Bean Validation with JEE 6 (JSR-303)

In this article I will show you some basic Bean Validation examples. You may want to (you should) read the official JSR 303 document to learn more. First, a quote from that document.

Validating data is a common task that occurs throughout an application, from the presentation layer to the persistence layer. Often the same validation logic is implemented in each layer, proving to be time consuming and errorprone. To avoid duplication of these validations in each layer, developers often bundle validation logic directly into the domain model, cluttering domain classes with validation code that is, in fact, metadata about the class itself.

This JSR defines a metadata model and API for JavaBean validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML validation descriptors.



Built-in constraints


To use built-in constraints your project must import the javax.validation dependency. Maven:

     <dependency>
         <groupId>javax.validation</groupId>
         <artifactId>validation-api</artifactId>
         <version>1.0.0.GA</version>
         <type>jar</type>
         <scope>test</scope>
     </dependency>

Here are some built-in annotations:
  • @Null
  • @NotNull
  • @AssertTrue
  • @AssertFalse
  • @Min
  • @Max
  • @DecimalMin
  • @DecimalMax
  • @Size - covers min and max
  • @Digits
  • @Past - must be a date in the past
  • @Future - must be a date in the future
  • @Pattern

Usage:
import javax.validation.constraints.Size;
import javax.validation.constraints.NotNull;

 // ...
 @NotNull
 @Size(min = 3)
 public String getName() {
     return name;
 }
UPDATE: @Min is for numbers only, my bad. This code now uses @Size.

Testing the validation


Here’s an example of unit testing constraints. You must add a Bean Validation implementation:
     <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-validator</artifactId>
         <version>4.0.2.GA</version>
         <type>jar</type>
         <scope>test</scope>
     </dependency>

And the code itself:
package me.m1key.jsf;

import static org.junit.Assert.assertEquals;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.junit.BeforeClass;
import org.junit.Test;

public class DogsBeanTest {
 private static Validator validator;

 @BeforeClass
 public static void setUp() {
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
     validator = factory.getValidator();
 }

 @Test
 public void test() {
     DogsBean bean = new DogsBean();

     Set<ConstraintViolation<DogsBean>> constraintViolations = validator
             .validate(bean);
     assertEquals(1, constraintViolations.size());
 }

}
It could be a lot better, because I only check the size of the violations set here. You might check the actual error message (still not so elegant...).


Error messages


Error messages are customizable. They can be modified if you provide a ResourceBundle called ValidationMessages (so, you can create a ValidationMessages .properties file and make if available in the classpath root).


When does validation occur?


Very good question! The specification doesn’t explicitly say when; instead it provides a clue in form of Appendices D, E and F.

Different JEE technologies launch Bean Validation. But when?

JPA calls validation upon:
  • pre-persist
  • pre-update
  • pre-remove
And these are entity lifecycle events. See Section 3.6 of JSR 317 for more details.

JSF calls validation upon:
  • the process validation phase
See Section 2.5.7 of JSR 314 for more details.


Next article


In the next article I will show you how to define custom constraints and more.

2010-07-13

CDI + JSF 2.0. Part 2

In my previous posts I showed a sample JSF 2.0 + Maven configuration and basic features of CDI with JSF 2.0. In this article I will show you the @Produces annotation and Alternatives, as well as unit testing of CDI.


@Produces


The @Produces annotation can be applied to a (private or other) field or a method. That means that you can inject not only beans, but also collections etc. Using the @Produce annotation you may also fine the criteria when you combine it with qualifiers.

Here’s an example from the official JSR 299 document. My sample application also utilizes the annotation but in a simpler manner.

public class Shop {

@Produces @All

public List<Product> getAllProducts() { ... }

@Produces @WishList

public List<Product> getWishList() { ... }
}

You can read more about alternatives in Section 3.3.2 of JSR.


@Alternative


You may have a few possibilities for a dependency injection. You can either use qualifiers (see Part 1) or the @Alternative annotation (you have to pick either approach or your CDI implementation will complain).

If you decide to use alternatives, you choose one default bean and annotate the rest with the @Alternative annotation. Then, you can change the one to be injected using your beans.xml file.

<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
 <alternatives>
     <class>me.m1key.jsf.dao.DogsDaoMockImpl</class>
 </alternatives>
</beans>

Remember that for this to work, the two beans (the one without the @Alternative annotation and the alternative one) must be on the same level of priority, i.e. have no or the same qualifiers etc.


Testing


No modern framework or toolkit can be considered mature without making it possible to run tests in isolation, without a server. What does testing look like with CDI?

I based my research on a post by Jacek Laskowski (the text is Polish, but the source code isn’t).

You need to provide your own implementation of CDI. We are going to use Arquillian and Weld.

Here’s the relevant pom.xml part:

<dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>org.jboss.weld</groupId>
              <artifactId>weld-core-bom</artifactId>
              <version>1.0.1-Final</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
  </dependencyManagement>
  <dependencies>
      <dependency>
          <groupId>javax.inject</groupId>
          <artifactId>javax.inject</artifactId>
          <version>1</version>
          <type>jar</type>
          <scope>provided</scope>
      </dependency>
      <dependency>
          <groupId>javax.enterprise</groupId>
          <artifactId>cdi-api</artifactId>
          <version>1.0-SP1</version>
          <type>jar</type>
          <scope>provided</scope>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.8.1</version>
          <type>jar</type>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.jboss.arquillian</groupId>
          <artifactId>arquillian-junit</artifactId>
          <version>1.0.0.Alpha2</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.jboss.arquillian.container</groupId>
          <artifactId>arquillian-weld-embedded</artifactId>
          <version>1.0.0.Alpha2</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.jboss.weld</groupId>
          <artifactId>weld-core</artifactId>
          <version>1.0.1-Final</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.jboss.weld</groupId>
          <artifactId>weld-api</artifactId>
          <version>1.0</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-simple</artifactId>
          <version>1.5.10</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>javax.el</groupId>
          <artifactId>el-api</artifactId>
          <version>2.2</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.jboss.weld.servlet</groupId>
          <artifactId>weld-servlet</artifactId>
          <version>1.0.1-Final</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
  <repositories>
      <repository>
          <id>JBoss.org</id>
          <name>JBoss Repository</name>
          <url>http://repository.jboss.com/maven2</url>
      </repository>
      <repository>
          <id>jboss-public-repository-group</id>
          <name>JBoss Public Maven Repository Group</name>
          <url>https://repository.jboss.org/nexus/content/groups/public/</url>
      </repository>
  </repositories>

And now the test itself.

package me.m1key.jsf;

import static org.junit.Assert.assertNotNull;

import java.io.File;
import java.io.IOException;

import javax.inject.Inject;

// ..

import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class DogsDaoTest {

  @Deployment
  public static JavaArchive createTestArchive()
          throws IllegalArgumentException, IOException {
      return ShrinkWrap.create("test.jar", JavaArchive.class)
              .addManifestResource(new File("src/test/resources/beans.xml"),
                      ArchivePaths.create("beans.xml")).addClasses(
                      DogsDaoImpl.class, DogsDaoMockImpl.class);
  }

  @Inject
  private DogsDao dogsDao;

  @Test
  public void testInjectedDaoNotNull() {
      assertNotNull(dogsDao);
      System.out.println(dogsDao.getClass().getCanonicalName());
  }

}

It’s a Maven project - and our test resources folder will contain another beans.xml. In this beans.xml we will specify alternative dependencies to inject (mock DAOs).

<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
 http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
 <alternatives>
     <class>me.m1key.jsf.dao.DogsDaoMockImpl</class>
 </alternatives>
</beans>

  • @RunWith(Arquillian.class) - we need this for Arquillian to be activated for the tests
  • @Deployment - it is an Arquillian’s requirement for one method with this annotation to be present. It builds an archive which contains all our tests need to run. You must manually specify which classes it should use. We are also loading the other beans.xml with alternative beans specified
  • @Inject - here a bean will be injected by our combination of Arquillian and Weld (namely, DogsDaoMockImpl)
  • The test method only checks if anything was injected


Summary


I showed you how to use the @Produce and @Alternative annotations. You can check out the source code to see it working. NOTE: I removed qualifiers so that @Alternative can work.

We also looked at testing possibilities from JUnit .

Download sample source code for this article

2010-07-12

StackOverflowError when using CDI

It seems that the current Weld implementation has an error - when no faces-config.xml is present in the deployment, but beans.xml is - you may get a StackOverflowError. At least I did with JBoss 6 RC3.

I filed the bug.

2010-07-11

CDI + JSF 2.0. Part 1

In my previous post I complained about the standard JSF dependency injection mechanism. Therefore I decided it was the right time to look at...

CDI - Contexts and Dependency Injection (JSR 299)


It might be a good idea to read the JSR 299 document (the evaluation version is for you; the other one is for JSR implementers like Guice or Spring) if you haven’t yet.

CDI (formerly known as Web Beans) differs from DI in that it introduces the concept of Context. So you can inject dependencies according to the context too. What contexts are there?
  • Application
  • Request
  • Session
  • Conversation
  • custom

That allows you to have a very flexible dependency injection mechanism where a new object is created by the container and injected whenever it does not exist in your context (or in broader context).


No more @ManagedBean


That’s right. This is how your JSF managed bean will look like now:

package me.m1key.jsf;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

// ...

@Named
@RequestScoped
public class DogsBean {   

In fact, we wouldn’t have to use the @Named annotation to make it a managed bean, because according to the specification (consult JSR) most Java classes are managed beans (i.e. you can use dependency injection in them or inject them). We need @Named, however, to reference that bean from JSF. You can specify another name (the default one is dogsBean in this case).


Accessing a managed bean from JSF


It’s simple.
<h:form>

<h:inputText value="#{dogsBean.name}" />

<h:commandButton value="Send" action="#{dogsBean.send}" />
</h:form>
And that’s it. Our bean is request scoped (CAUTION: make sure you import @RequestScoped from the correct package! That is javax.enterprise.context and not javax.faces.bean) so there will be a new instance of it per request.

Let’s take a look at...

Dependency injection


Let’s create a DAO.

package me.m1key.jsf.dao;

// ...

public interface DogsDao {

 public List<Dog> retrieveAllDogs();

}

package me.m1key.jsf.dao;

import javax.enterprise.context.ApplicationScoped;
// ...

@ApplicationScoped
public class DogsDaoImpl implements DogsDao {

 public DogsDaoImpl() {
     System.out.println(" DogsDaoImpl created: " + this);
 }

 public List<Dog> retrieveAllDogs() {
     List<Dog> dogs = new ArrayList<Dog>();

     Dog dog1 = new Dog();
     dog1.setId(1L);
     dog1.setName("Sega");
     dogs.add(dog1);

     Dog dog2 = new Dog();
     dog2.setId(2L);
     dog2.setName("Fluffy");
     dogs.add(dog2);

     return dogs;
 }

}

Great! This bean is Application scoped, so there is going to be one instance of it per application. Note: the constructor will be called twice, actually. One for the actual object, one for the proxy. Read more about this behavior or consult JSR 299, Section 5.4.

Now, let’s inject it.

 @Inject
 private DogsDao dogsDao;

That’s it. You ask for an interface injection. The container sees there is only one implementation, and injects it. But what if you want to have two implementations of DogsDao?

package me.m1key.jsf.dao;

import javax.enterprise.context.ApplicationScoped;

// ...

@ApplicationScoped    
public class DogsDaoMockImpl implements DogsDao {

With the current configuration, you’d get an exception - the container would not be able to decide which one to instantiate for you. How can you further specify which implementation you need? You should use...

Qualifiers


Qualifiers are a CDI concept that allows you to have more sophisticated criteria for selecting the implementation. Let’s create two qualifiers.

package me.m1key.jsf.qualifiers;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
     ElementType.TYPE })
public @interface Actual {}

package me.m1key.jsf.qualifiers;

// ...

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
     ElementType.TYPE })
public @interface Mock {}

Qualifiers must be annotated with @Qualifier.

Now, let’s annotate the classes.

// ...
import me.m1key.jsf.qualifiers.Actual;

@Actual
@ApplicationScoped
public class DogsDaoImpl implements DogsDao {

// ...
import me.m1key.jsf.qualifiers.Mock;

@Mock
@ApplicationScoped
public class DogsDaoMockImpl implements DogsDao {

Now, when we inject, we must specify which implementation we want, with the same qualifier.

@Inject
@Actual
private DogsDao dogsDao;

And now it works.


Summary


I explained how to use basic CDI which is a new feature of JEE6. Remember that this is a JSF example, so I assumed you run it on an application server. However, CDI itself can be run without a server, so long as you provide an implementation for it (like Weld; the situation is similar to JPA).

Download source code for this article

Next article


In the next article I will explain why and how you can use the @Produces annotation and how to use alternatives (alternatives in the CDI sense).

2010-07-08

JSF 2.0 + Maven

In this article I will show you how to create a basic JSF 2.0 application with Maven, for JBoss 6.0.0-RC3.


JSF 2.0


JSF is a framework for building web applications using reusable components, and it’s focused on UI components. This allows you to write less HTML, which is a good thing.

What’s new compared to JSF 1.x?


In this article


I will present basic configuration of a JSF 2.0 project with Maven. Nothing fancy.


Maven pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>me.m1key.jsf</groupId>
  <artifactId>sample</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <build>
      <finalName>sample</finalName>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>2.0.2</version>
              <configuration>
                  <source>1.6</source>
                  <target>1.6</target>
              </configuration>
          </plugin>
      </plugins>
  </build>
  <dependencies>
      <dependency>
          <groupId>javax.faces</groupId>
          <artifactId>jsf-api</artifactId>
          <version>2.0.2-FCS</version>
          <scope>provided</scope>
      </dependency>
      <dependency>
          <groupId>javax.faces</groupId>
          <artifactId>jsf-impl</artifactId>
          <version>2.0.2-FCS</version>
          <scope>provided</scope>
      </dependency>
  </dependencies>
  <repositories>
      <repository>
          <id>JBoss.org</id>
          <name>JBoss Repository</name>
          <url>http://repository.jboss.com/maven2</url>
      </repository>
  </repositories>
</project>

Why those versions of JSF? Well, that’s exactly what JBoss 6.0.0-RC3 uses.


faces-config.xml


No faces-config.xml - we don’t need it!


Managed bean


package me.m1key.jsf;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class UserBean {
  private String name;

  public String getName() {
      return name;
  }

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

  public String send() {
      return "hello";
  }
}

Because we are using the @ManagedBean annotation, we don’t need to declare the bean anywhere else. You can override this configuration with faces-config.xml, if you need to.

The send() method returns a String “hello". Automatically, .xhtml is going to be appended to it and a view hello.xhtml will be resolved. No need to declare the rule. Convention over configuration.

The default scope of this bean is request. You can modify the default scope.

// ...
// import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;

@ManagedBean
// @RequestScoped
@SessionScoped
public class UserBean {
// ...

  • @RequestScoped
  • @SessionScoped
  • @ApplicationScoped - one bean for all
  • @ViewScoped - the same bean is used as long as the user stays on the page (this is for AJAX)
  • @CustomScoped - stores the bean in a map; developer controls it
  • @NoneScoped - not in scope. Normally referenced by other beans that are in scope

Because it’s a managed bean, you can use JEE goodies (such as @EJB etc.) if you run your application on a JEE server .

Read more about managed beans validation and dependency injection using annotations.

I think that the JSF way of doing dependency injection is somewhat cumbersome. If you’re on JEE 6, you may want to use the new CDI mechanism. Jacek Laskowski wrote an article on using CDI with Java SEE (so without a JEE6 server). The article is in Polish, but the source code isn’t.


web.xml


<!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Web Application</display-name>

  <context-param>
      <param-name>javax.faces.PROJECT_STAGE</param-name>
      <param-value>Development</param-value>
  </context-param>

  <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>
</web-app>

Note the PROJECT_STAGE property. It’s new to JSF 2.0. You can read more about PROJECT_STAGE on Ryan Lubke’s blog.


The views


The view with a form:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

  <h:head>
      <title>Index</title>
  </h:head>
  
  <h:body>
      <h:form>
          <h:inputText value="#{userBean.name}" />
          <h:commandButton value="Send" action="#{userBean.send}" />
      </h:form>
  </h:body>

</html>

The result view:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

  <h:head>
      <title>Hello</title>
  </h:head>
  
  <h:body>
      <h1>Hello #{userBean.name}</h1>
  </h:body>

</html>


Summary


We created a simple JSF 2.0 application that uses a single managed bean and has 2 views. On that I will build another example, perhaps something using CDI.

Download source code for this article