Category Archives: JSF

Define Restful web services using Spring

In one of my project, I had the difficult decision to switch to another technology: I replaced JSF with Angular-JS.
Our goal was to speed up the development by removing the painful part implied with JSF, as a lot of server requests to manage, some view state issues, the refresh management, the need to implement the view on the Java part with its managed beans, etc…

But the big impact on the architectural point of view was that we have to move the GUI (and its logic) on the client side and give access to the data. Fortunately, this part was ease by the layered structure of the application, I just need to replace the old JSF part with a REST interface which is accessed by the Angular-JS components using Ajax requests.
As the project used already Spring, I decided to use it also to set up the restful part, I describe hereafter what I did.

First of all, we need to add the corresponding dependencies in our POM:

<properties>
    <spring.framework.version>4.0.5.RELEASE</spring.framework.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.framework.version}</version>
    </dependency>
            <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.framework.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.4</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.12</version>
    </dependency>
</dependencies>

We need also to activate the configuration using annotation, for that we have to add in our Spring configuration file:

    <context:component-scan base-package="net.classnotfound.ws"/>
    <mvc:annotation-driven />

Even if I do not like to use the annotations to configure the application, I decided to make an exception for the web services, as they are not intended to have some intelligence and are just a bridge to the business layer, I consider it as acceptable.

A web service is declared using the @RestController Spring annotation:

package net.classnotfound.ws.controller;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
	//Web service implementation here
    
}

When we define an endpoint for the web service, we need to indicates which HTTP method we use, the type of data we expect (JSON is the usual case), etc…
This can be done easily by using the Spring annotation:

    @RequestMapping(value = "/service/print", method = RequestMethod.POST, consumes = {"application/json" })
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void print(@RequestBody final Data data) {
        System.out.println(data);
    }

Here, we defined a method print, which is reachable using “/service/print” URL, using a POST request with data in JSON format.
The @ResponseStatus is used to define the HTTP return code to be used.

Another option is to use a GET method, but doing this, the parameters are now directly provided with the requested URL:

    @Autowired
    private DataService dataService;

    @Transactional
    @Globals
    @RequestMapping(value = "/service/data/{id}", method = RequestMethod.GET)
    @ResponseBody
    public Data find(@PathVariable("id") final String id) {
        Data data = dataService.find(id);
        if (data==null) {
            throw new ObjectNotFoundException(id);
        }
        return data;
    }

We can see the parameter defined in the URL using a EL syntax and this parameter is also mentioned in the signature of the method using @PathVariable annotation.

Too easy, isn’t it? 😀

Display Maven release number in JSF page

In the web projects, it is often useful to see quickly the version of the deployed application. A simple solution is to get it from Maven and display it in our page, in footer or a “about” page.
The main idea is to use a property file as a JSF resource as we can use, for example, when we have a i18n requirement.
For that, I put a property file version.properties with content in the resource directory:

version=${version}
revision=${buildNumber}

The version is the version defined in our project pom and it is automatically provided by Maven.
The revision is the revision number of the last build provided by SVN, to get it, I will need another Maven plugins.

Now, I need to tell to JSF to use this file as resource file, I do it in my faces-config.xml:

<application>
	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
	<resource-bundle>
	   <base-name>version</base-name>
	   <var>vers</var>
	</resource-bundle>
</application>

And to display it in our JSF pages, I add:

<body>
   [...]
	<div>classNotFound.net ©2014 -
		v#{vers.version} - #{vers.revision}</div>
</body>

If I try to access to this page, I will not see the version/revision, to do that, I have to ask Maven to filter the properties files and replace the variables.
In my pom.xml, I add:

<build>
	<resources>
		<resource>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
			<includes>
				<include>**/*</include>
			</includes>
		</resource>
	</resources>
</build>

To have the build number, I have to use 3 Maven plugins:

<pluginManagement>
        <plugins>
            <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>buildnumber-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>validate</phase>
                    <goals>
                        <goal>create</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <doCheck>false</doCheck>
                <doUpdate>false</doUpdate>
                <providerImplementations>
                    <svn>javasvn</svn>
                </providerImplementations>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>com.google.code.maven-scm-provider-svnjava</groupId>
                    <artifactId>maven-scm-provider-svnjava</artifactId>
                    <version>2.0.2</version>
                </dependency>
                <dependency>
                    <groupId>org.tmatesoft.svnkit</groupId>
                    <artifactId>svnkit</artifactId>
                    <version>1.7.5-v1</version>
                </dependency>
            </dependencies>
        </plugin>
        </plugins>
    </pluginManagement>
  </build>
  
    <scm>
        <connection>scm:svn:https://forge.classnotfound.net/svn/version/trunk/project/project-web</connection>
        <developerConnection>scm:svn:https://forge.classnotfound.net/svn/project/trunk/project/project-web</developerConnection>
        <url>https://forge.classnotfound.net/svn/project/trunk/project/project-web</url>
    </scm>

Now, it works.

Spring Security with JSF 2 and custom login form

Here, I am integrating Spring Security with JSF 2 using a custom login form.

First, the maven dependencies for Spring-Security (I consider that the JSF project is already set-up, if it is not the case, you can check here):

<properties>
    ...
    <spring.security.version>3.2.4.RELEASE</spring.security.version>
</properties>
...
<!-- Spring-Security dependencies -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${spring.security.version}</version>
</dependency>

In the web.xml, we have to configure the Spring-Security filter as follow:

<!-- Enable Spring Filter: Spring Security works on the concept of Filters -->
<!-- Declare the Spring filter -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>
<!-- Defines urls pattern on which the filter is applied -->
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

Note: if you don’t add the forward to it, the managed bean will not be able to send the request to the filter (I experienced that!!).

We need a simple index.xhtml which will be protected by Spring (I don’t describe it here) and a custom login page which receive the credentials typed by the user.
This page contains only the user name, the password and another field method which is here to show how we can get it on the server:

<h:form id="loginFormId" prependId="false">
    <div class="full-box" style="text-align: center">
        <div class="child-box box-c3">
            <h3>Login</h3>
            <div class="fluid-row">
                <div class="fluid-column fluid-c12">
                    <div class="forLabel" style="width: 30%">
                        <h:outputLabel for="username" value="User" />
                    </div>
                    <div class="forField" style="width: 65%">
                        <h:inputText id="username" required="true"
                            requiredMessage="Please enter username (or go to hell...)" />
                        <h:messages for="username" />
                    </div>
                </div>
                <div class="fluid-column fluid-c12">
                    <div class="forLabel" style="width: 30%">
                        <h:outputLabel for="password" value="Password" />
                    </div>
                    <div class="forField" style="width: 65%">
                        <h:inputSecret id="password" required="true"
                            requiredMessage="Please enter password (otherwise you'll die!!)"
                            name="password" />
                        <h:messages for="password" />
                    </div>
                </div>
                <div class="fluid-column fluid-c12">
                    <div class="forLabel" style="width: 30%">
                        <h:outputText value="Authentication" />
                    </div>
                    <div class="forField" style="width: 65%">
                        <h:selectBooleanCheckbox id="method" name="method" />
                        <h:outputLabel for="method" value="LDAP" />
                    </div>
                </div>
            </div>
            <ui:fragment rendered="${!empty param['error']}">
                <div>Connection failed: user and/or password are wrong.</div>
            </ui:fragment>
            <div id="loginBtnPanelId">
                <h:commandButton id="btnLoginId" value="Login" type="submit"
                    action="${loginManager.doLogin()}" styleClass="loginPanelBtn" />
            </div>
        </div>
    </div>
</h:form>

The form is very simple, we can see the 3 fields and a portion which is conditionally rendered if error param is available.
The content of this form is sent to a managed bean which is responsible of forwarding data to the Spring-Security filter:

import java.io.IOException;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

@ManagedBean
@RequestScoped
public class LoginManager {

    public String doLogin() throws IOException, ServletException {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/j_spring_security_check");
        dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
        FacesContext.getCurrentInstance().responseComplete();
        return null;
    }

}

Now, we need to have a look to the Spring configuration file, the security is configured as follow:

<security:http use-expressions="true">
    <!-- refers to http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html -->
    <security:intercept-url pattern="/faces/login.xhtml"
        access="anonymous" />
    <security:intercept-url pattern="/css/**"
        access="anonymous" />
    <security:intercept-url pattern="/**"
        access="authenticated" />
    <security:form-login login-page="/faces/login.xhtml"
        authentication-failure-url="/faces/login.xhtml?error=1"
        default-target-url="/faces/index.xhtml"
        authentication-details-source-ref="myAuthenticationDetailsSource"
        username-parameter="username" password-parameter="password" />
</security:http>

We can see that we have to enable anonymous access to the login form (otherwise, you will see some strange messages in your browser, I let you guess why). To have a beautiful login page, we also allow anonymous access to the CSS, the rest of the site has a restricted access controlled by Spring.
As we use a custom login form, the form-login element must indicate which one we want to use with the login-page attribute.
To be able to store the custom field (the method if you forgot it), we have to implement a custom class, it is the one we see in the authentication-details-source-ref attribute.

This is how it is defined in the Spring configuration file:

<bean id="myAuthenticationDetailsSource"
    class="net.classnotfound.jsf.spring.security.security.MyAuthenticationDetailsSource">
</bean>

And the class which implements the org.springframework.security.authentication.AuthenticationDetailsSource interface:

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

/**
 * This class provides a custom AuthenticationDetail which stores the connection
 * type method (Oracle/Ldap)
 *
 */
public class MyAuthenticationDetailsSource implements AuthenticationDetailsSource {

    /**
     * returns the {@link WebAuthenticationDetails} according to LuxFact rule
     * 
     * @param context
     */
    @Override
    public WebAuthenticationDetails buildDetails(final HttpServletRequest context) {
        return new MyAuthenticationDetails(context);
    }

}

This class provides an implementation of a org.springframework.security.web.authentication.WebAuthenticationDetails which will store our extra parameter, its implementation is very simple:

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.web.authentication.WebAuthenticationDetails;

/**
 * this class stores data used for authentication (mainly the authentication
 * method)
 * 
 */
public class MyAuthenticationDetails extends WebAuthenticationDetails {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private final String method;

    public MyAuthenticationDetails(final HttpServletRequest request) {
        super(request);
        method = request.getParameter("method");
    }

    public String getMethod() {
        return method;
    }

}

As we can see, this class does nothing else than getting the custom parameter from the request and storing it.

Now, to use this extra parameter, we need to customize the way a user is authenticated. As this task is, by default, done by Spring, it means that we have to write a new class which implements the org.springframework.security.authentication.AuthenticationProvider interface. We can see its declaration in the Spring configuration file here:

<bean id="myAuthenticationProvider"
    class="net.classnotfound.jsf.spring.security.security.MyAuthenticationProvider">
</bean>

<security:authentication-manager>
    <!-- create a custom AuthenticationProvider class to tune the login 
        process -->
    <security:authentication-provider
        ref="myAuthenticationProvider" />
</security:authentication-manager>

And its implementation:

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

public class MyAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(final Authentication authentication) throws AuthenticationException {

        Authentication res = isValid(authentication);
        if (!res.isAuthenticated()) {
            throw new BadCredentialsException("Bad credentials");
        }
        return res;
    }

    private Authentication isValid(final Authentication authentication) {
        Authentication res = authentication;
        System.out.println("Selected method: "+((MyAuthenticationDetails)authentication.getDetails()).getMethod());
        if ("Admin".equals(authentication.getPrincipal())&&"Password".equals(authentication.getCredentials())) {
            res = createSuccessAuthentication(authentication);
        }
        return res;
    }

    @Override
    public boolean supports(final Class authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

    protected Authentication createSuccessAuthentication(final Authentication authentication) {
        // Ensure we return the original credentials the user supplied,
        // so subsequent attempts are successful even with encoded passwords.
        // Also ensure we return the original getDetails(), so that future
        // authentication events after cache expiry contain the details
        final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), authentication.getAuthorities());
        result.setDetails(authentication.getDetails());

        return result;
    }

}

As we can see, the extra parameter is extracted from the org.springframework.security.core.Authentication.getDetails() method.

The whole Spring configuration file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    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">


    <!-- Enable security annotations usage -->

    <bean id="myAuthenticationDetailsSource"
        class="net.classnotfound.jsf.spring.security.security.MyAuthenticationDetailsSource">
    </bean>

    <bean id="myAuthenticationProvider"
        class="net.classnotfound.jsf.spring.security.security.MyAuthenticationProvider">
    </bean>


    <security:authentication-manager>
        <!-- create a custom AuthenticationProvider class to tune the login 
            process -->
        <security:authentication-provider
            ref="myAuthenticationProvider" />
    </security:authentication-manager>

    <security:http use-expressions="true">
        <!-- refers to http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html -->
        <security:intercept-url pattern="/faces/login.xhtml"
            access="anonymous" />
        <security:intercept-url pattern="/css/**"
            access="anonymous" />
        <security:intercept-url pattern="/**"
            access="authenticated" />
        <security:form-login login-page="/faces/login.xhtml"
            authentication-failure-url="/faces/login.xhtml?error=1"
            default-target-url="/faces/index.xhtml"
            authentication-details-source-ref="myAuthenticationDetailsSource"
            username-parameter="username" password-parameter="password" />
    </security:http>

</beans>

Source files are available here.

Maven config for JSF2/RichFaces

Here is my Maven configuration for a JSF2/Richfaces project:

<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>net.classnotfound</groupId>
    <artifactId>jsf</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>jsf</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <org.apache.myfaces.version>2.2.0</org.apache.myfaces.version>
        <org.richfaces.version>4.3.5.Final</org.richfaces.version>
    </properties>

    <dependencies>

        <!-- web container dependencies -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>7.0.50</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSF dependencies -->
        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-bundle</artifactId>
            <version>${org.apache.myfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>2.1</version>
        </dependency>
        <!-- end JSF dependencies -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- RichFaces dependencies -->
        <dependency>
            <groupId>org.richfaces.core</groupId>
            <artifactId>richfaces-core-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.core</groupId>
            <artifactId>richfaces-core-impl</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui.common</groupId>
            <artifactId>richfaces-ui-common-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui.core</groupId>
            <artifactId>richfaces-ui-core-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui</groupId>
            <artifactId>richfaces-components-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui</groupId>
            <artifactId>richfaces-components-ui</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.w3c.css</groupId>
            <artifactId>sac</artifactId>
            <version>1.3</version>
        </dependency>
        <!-- End RichFaces dependencies -->
    </dependencies>
</project>