Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.
You searched this site for "xsd". 16 entries found.

You can also try this same search on Google.

Building a REST API with JAXB, Spring Boot and Spring Data

Project JAXB If someone asked you to develop a REST API on the JVM, which frameworks would you use? I was recently tasked with such a project. My client asked me to implement a REST API to ingest requests from a 3rd party. The project entailed consuming XML requests, storing the data in a database, then exposing the data to internal application with a JSON endpoint. Finally, it would allow taking in a JSON request and turning it into an XML request back to the 3rd party.

With the recent release of Apache Camel 2.14 and my success using it, I started by copying my Apache Camel / CXF / Spring Boot project and trimming it down to the bare essentials. I whipped together a simple Hello World service using Camel and Spring MVC. I also integrated Swagger into both. Both implementations were pretty easy to create (sample code), but I decided to use Spring MVC. My reasons were simple: its REST support was more mature, I knew it well, and Spring MVC Test makes it easy to test APIs.

Camel's Swagger support without web.xml
As part of the aforementioned spike, I learned out how to configure Camel's REST and Swagger support using Spring's JavaConfig and no web.xml. I made this into a sample project and put it on GitHub as camel-rest-swagger.

This article shows how I built a REST API with Java 8, Spring Boot/MVC, JAXB and Spring Data (JPA and REST components). I stumbled a few times while developing this project, but figured out how to get over all the hurdles. I hope this helps the team that's now maintaining this project (my last day was Friday) and those that are trying to do something similar.

[Read More]

Posted in Java at Oct 29 2014, 05:52:37 AM MDT 2 Comments

A Webapp Makeover with Spring 4 and Spring Boot

A typical Maven and Spring web application has a fair amount of XML and verbosity to it. Add in Jersey and Spring Security and you can have hundreds of lines of XML before you even start to write your Java code. As part of a recent project, I was tasked with upgrading a webapp like this to use Spring 4 and Spring Boot. I also figured I'd try to minimize the XML.

This is my story on how I upgraded to Spring 4, Jersey 2, Java 8 and Spring Boot 0.5.0 M6.

When I started, the app was using Spring 3.2.5, Spring Security 3.1.4 and Jersey 1.18. The pom.xml had four Jersey dependencies, three Spring dependencies and three Spring Security dependencies, along with a number of exclusions for "jersey-spring".

Upgrading to Spring 4
Upgrading to Spring 4 was easy, I changed the version property to 4.0.0.RC2 and added the new Spring bill of materials to my pom.xml. I also add the Spring milestone repo since Spring 4 won't be released to Maven central until tomorrow.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>${spring.framework.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<repositories>
    <repository>
        <id>spring-milestones</id>
        <url>http://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
[Read More]

Posted in Java at Dec 11 2013, 12:47:15 PM MST 7 Comments

Upgrading AppFuse to Spring Security 3.1 and Spring 3.1

Before the holiday break, I spent some time upgrading AppFuse to use the latest releases of Spring and Spring Security. I started with Spring Security in early December and quickly discovered its 3.1 XSD required some changes. After changing to the 3.1 XSD in my security.xml, I had to change its <http> element to use security="none" instead of filters="none". With Spring Security 3.0.5, I had:

<http auto-config="true" lowercase-comparisons="false">
    <intercept-url pattern="/images/**" filters="none"/>
    <intercept-url pattern="/styles/**" filters="none"/>
    <intercept-url pattern="/scripts/**" filters="none"/>
After upgrading to 3.1, I had to change this to:
<http pattern="/images/**" security="none"/>
<http pattern="/styles/**" security="none"/>
<http pattern="/scripts/**" security="none"/>

<http auto-config="true">

The next thing I had to change was UserSecurityAdvice.java. Instead of using Collection<GrantedAuthority> for Authentication's getAuthority() method, I had to change it to use Collection<? extends GrantedAuthority>.

Authentication auth = ctx.getAuthentication();
Collection<? extends GrantedAuthority> roles = auth.getAuthorities();

Lastly, I discovered that SPRING_SECURITY_CONTEXT_KEY moved to HttpSessionSecurityContextRepository. Click here to see the changelog for this upgrade in AppFuse's FishEye.

You can read more about what's new in Spring Security 3.1 on InfoQ. I'm especially pumped to see http-only cookie support for Servlet 3.0. I discovered Spring Security didn't support this when Pen-Testing with Zed Attack Proxy.

Upgrading to Spring Framework 3.1
Compared to the Spring Security upgrade, upgrading to Spring 3.1 was a breeze. The first thing I discovered after changing my pom.xml's version was that Spring Security required some additional exclusions in order to get the latest Spring versions. Of course, this was communicated to me through the following cryptic error.

-------------------------------------------------------------------------------
Test set: org.appfuse.dao.LookupDaoTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.004 sec <<< FAILURE!
testGetRoles(org.appfuse.dao.LookupDaoTest)  Time elapsed: 0.001 sec  <<< ERROR!
java.lang.NoSuchMethodError: org.springframework.context.support.GenericApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment;
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:97)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
	at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)

Without these additional exclusions, Spring Security pulled in Spring 3.0.6. I had to exclude spring-expression, spring-context and spring-web from spring-security-taglibs to get the 3.1.0.RELEASE version of Spring.

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

I also had to exclude spring-context from spring-security-config and spring-context and spring-expression from spring-security-core. Isn't Maven wonderful?

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
</dependency>

After making these changes, I got a bit further, but ended up being blocked by a bug in Tapestry 5's Spring support. Basically, after upgrading to Spring 3.1, I started seeing the following error:

java.lang.RuntimeException: Service id 'environment' has already been defined by 
org.apache.tapestry5.services.TapestryModule.buildEnvironment(PerthreadManager) 

Luckily, I was able to easily fix this with advice I found on Tapestry's mailing list. Unfortunately, even though I submitted a fix on December 15th, it didn't make it into Tapestry's 5.3.1 release on December 21st. As soon as Tapestry 5.3.2 is released, I hope to get the AppFuse's build passing again (it's currently failing).

I hope this article helps you upgrade your AppFuse-started applications to the latest versions of Spring and Spring Security. Over the next few weeks, I'll be exploring many of Spring 3.1's new features and implementing them as I see fit. Right now, I'm thinking environments/profiles, Servlet 3 / Java 7 support and Hibernate 4 support. These seem to be the best new features to learn about for my talk in a few weeks.

Posted in Java at Jan 05 2012, 08:58:21 AM MST 7 Comments

Integrating OAuth with AppFuse and its REST API

One of the new features in AppFuse 2.1 is an appfuse-ws archetype. This archetype leverages Enunciate and CXF to create a project with a REST API and generated HTML documentation. Enunciate is a very useful tool, allowing you to develop web services with JAX-RS and JAX-WS annotations and have all types of client libraries generated. For me, it seems very useful for developing the backend of SOFEA (a.k.a. modern) applications.

Back in March, Ryan Heaton published a nice article on Securing Web Services in an Enunciate application. I decided to take his tutorial a step further and not only secure my web services, but also to integrate with OAuth 2. In this tutorial, I'll show you how to create a new application with AppFuse WS, secure it, add OAuth support, and then use a client app to authenticate and retrieve data.

Create a New AppFuse WS Project
To begin, I visited the Create AppFuse Archetypes page and created a new application using the "Web Services Only" option in the Web Framework dropdown. Below is the command I used to create the "appfuse-oauth" project.

mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes \
-DarchetypeArtifactId=appfuse-ws-archetype -DarchetypeVersion=2.1.0 \
-DgroupId=org.appfuse.example -DartifactId=appfuse-oauth 

After doing this, I started the app using mvn jetty:run and confirmed it started OK. At this point, I was able to view the generated documentation for the application at http://localhost:8080. The screenshot below shows what the app looks like at this point.

AppFuse WS Homepage

NOTE: You might notice the REST endpoint of /{username}. This is a bug in AppFuse 2.1.0 and has been fixed in SVN. It does not affect this tutorial.

Integrate Spring Security and OAuth
I originally tried to integrate Spring Security with Enunciate's Securing Web Services Tutorial. However, it only secures endpoints and doesn't do enough filtering for OAuth support, so I ended up using a custom web.xml. I put this file in src/main/resources and loaded it in my enunciate.xml file. I also upgraded Spring Security and imported my security.xml file.

  <?xml version="1.0"?>
  <enunciate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.22.xsd">
      ...
      <webapp mergeWebXML="src/main/resources/web.xml"/>
      <modules>
      ...
          <spring-app disabled="false" springVersion="3.0.5.RELEASE">
              <springImport uri="classpath:/applicationContext-resources.xml"/>
              <springImport uri="classpath:/applicationContext-dao.xml"/>
              <springImport uri="classpath:/applicationContext-service.xml"/>
              <springImport uri="classpath:/applicationContext.xml"/>
              <springImport uri="classpath:/security.xml"/>
          </spring-app>
      </modules>
  </enunciate>

Then I created src/main/resources/web.xml with a filter for Spring Security and a DispatcherServlet for OAuth support.

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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/web-app_3_0.xsd"
         version="3.0">

    <filter>
        <filter-name>securityFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>springSecurityFilterChain</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>securityFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>appfuse-oauth</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appfuse-oauth</servlet-name>
        <url-pattern>/oauth/*</url-pattern>
    </servlet-mapping>
</web-app>

Next, I created a src/main/resources/security.xml and used it to secure my API, specify a login page, supply the users and integrate OAuth (see the last 4 beans below).

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
                           http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

    <http auto-config="true">
        <intercept-url pattern="/api/**" access="ROLE_USER"/>
        <intercept-url pattern="/oauth/**" access="ROLE_USER"/>
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true"
                    login-processing-url="/j_security_check"/>
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="admin" password="admin" authorities="ROLE_USER,ROLE_ADMIN"/>
                <user name="user" password="user" authorities="ROLE_USER"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>

    <!--hook up the spring security filter chain-->
    <beans:alias name="springSecurityFilterChain" alias="securityFilter"/>

    <beans:bean id="tokenServices"
                class="org.springframework.security.oauth2.provider.token.InMemoryOAuth2ProviderTokenServices">
        <beans:property name="supportRefreshToken" value="true"/>
    </beans:bean>

    <oauth:provider client-details-service-ref="clientDetails" token-services-ref="tokenServices">
        <oauth:verification-code user-approval-page="/oauth/confirm_access"/>
    </oauth:provider>

    <oauth:client-details-service id="clientDetails">
        <!--<oauth:client clientId="my-trusted-client" authorizedGrantTypes="password,authorization_code,refresh_token"/>
        <oauth:client clientId="my-trusted-client-with-secret"
                      authorizedGrantTypes="password,authorization_code,refresh_token" secret="somesecret"/>
        <oauth:client clientId="my-less-trusted-client" authorizedGrantTypes="authorization_code"/>-->
        <oauth:client clientId="ajax-login" authorizedGrantTypes="authorization_code"/>
    </oauth:client-details-service>
</beans:beans>

I used the OAuth for Spring Security sample apps to figure this out. In this example, I used authorizedGrantTypes="authorization_code", but you can see from the commented <oauth:client> elements above that there's a few different options. You should also note that the clientId is hard-coded to "ajax-login", signifying I only want to allow a single application to authenticate.

At this point, I'd like to give a shoutout to Ryan Heaton for creating both Enunciate and Spring Security's OAuth support. Nice work Ryan!

At this point, I needed to do a number of additional tasks to finish integrating oauth. The first was to modify the Jetty Plugin's configuration to 1) run on port 9000, 2) load my custom files and 3) allow jetty:run to recognize Enunciate's generated files. Below is the final configuration in my pom.xml.

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.26</version>
    <configuration>
        <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                <port>9000</port>
                <maxIdleTime>60000</maxIdleTime>
            </connector>
        </connectors>
        <webAppConfig>
            <baseResource implementation="org.mortbay.resource.ResourceCollection">
                <resourcesAsCSV>
                    ${basedir}/src/main/webapp,
                    ${project.build.directory}/${project.build.finalName}
                </resourcesAsCSV>
            </baseResource>
            <contextPath>/appfuse-oauth</contextPath>
        </webAppConfig>
        <webXml>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</webXml>
    </configuration>
</plugin>

Next, I added the necessary OAuth dependencies for Spring Security to my pom.xml. Since the latest release is a milestone release, I had to add Spring's milestone repo too.

<repository>
    <id>spring-milestone</id>
    <url>http://s3.amazonaws.com/maven.springframework.org/milestone</url>
</repository>
...
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${spring.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-support</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth</artifactId>
    <version>1.0.0.M3</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

Since I named my DispatcherServlet "appfuse-oauth" in web.xml, I created a src/main/webapp/WEB-INF/appfuse-oauth-servlet.xml to configure Spring MVC. I had to create the src/main/webapp/WEB-INF directory.

<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- Scans the classpath of this application for @Components to deploy as beans -->
    <context:component-scan base-package="org.appfuse.examples.webapp"/>

    <!-- Configures the @Controller programming model -->
    <mvc:annotation-driven/>

    <!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

In order to show the OAuth confirmation page, I needed to create src/main/java/org/appfuse/examples/webapp/AccessConfirmationController.java and map it to /oauth/confirm_access. I copied this from one of the sample projects and modified to use Spring's annotations.

package org.appfuse.examples.webapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientAuthenticationToken;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.verification.ClientAuthenticationCache;
import org.springframework.security.oauth2.provider.verification.DefaultClientAuthenticationCache;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.TreeMap;

/**
 * Controller for retrieving the model for and displaying the confirmation page
 * for access to a protected resource.
 *
 * @author Ryan Heaton
 */
@Controller
@RequestMapping("/confirm_access")
public class AccessConfirmationController {

    private ClientAuthenticationCache authenticationCache = new DefaultClientAuthenticationCache();
    @Autowired
    private ClientDetailsService clientDetailsService;

    @RequestMapping(method = RequestMethod.GET)
    protected ModelAndView confirm(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ClientAuthenticationToken clientAuth = authenticationCache.getAuthentication(request, response);
        if (clientAuth == null) {
            throw new IllegalStateException("No client authentication request to authorize.");
        }

        TreeMap<String, Object> model = new TreeMap<String, Object>();
        ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
        model.put("auth_request", clientAuth);
        model.put("client", client);

        return new ModelAndView("access_confirmation", model);
    }
}

This controller delegates to src/main/webapp/access_confirmation.jsp. I created this file and filled it with code to display Accept and Deny buttons.

<%@ page import="org.springframework.security.core.AuthenticationException" %>
<%@ page import="org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException" %>
<%@ page import="org.springframework.security.oauth2.provider.verification.BasicUserApprovalFilter" %>
<%@ page import="org.springframework.security.oauth2.provider.verification.VerificationCodeFilter" %>
<%@ page import="org.springframework.security.web.WebAttributes" %>
<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Confirm Access</title>
    <link rel="stylesheet" type="text/css" media="all"
          href="http://demo.appfuse.org/appfuse-struts/styles/simplicity/theme.css"/>
    <style type="text/css">
        h1 {
            margin-left: -300px;
            margin-top: 50px
        }
    </style>
</head>

<body>

<h1>Confirm Access</h1>

<div id="content">

    <% if (session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) != null && 
                 !(session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) instanceof UnapprovedClientAuthenticationException)) { %>
    <div class="error">
        <h2>Woops!</h2>

        <p>Access could not be granted.
            (<%= ((AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION)).getMessage() %>)</p>
    </div>
    <% } %>
    <c:remove scope="session" var="SPRING_SECURITY_LAST_EXCEPTION"/>

    <authz:authorize ifAnyGranted="ROLE_USER,ROLE_ADMIN">
        <h2>Please Confirm</h2>

        <p>You hereby authorize "<c:out value="${client.clientId}" escapeXml="true"/>" to access your protected resources.</p>

        <form id="confirmationForm" name="confirmationForm"
              action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="POST">
            <input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>"
                   value="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/>
            <label><input name="authorize" value="Authorize" type="submit"></label>
        </form>
        <form id="denialForm" name="denialForm"
              action="<%=request.getContextPath() + VerificationCodeFilter.DEFAULT_PROCESSING_URL%>" method="POST">
            <input name="<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_REQUEST_PARAMETER%>"
                   value="not_<%=BasicUserApprovalFilter.DEFAULT_APPROVAL_PARAMETER_VALUE%>" type="hidden"/>
            <label><input name="deny" value="Deny" type="submit"></label>
        </form>
    </authz:authorize>
</div>
</body>
</html>

Finally, I needed to create src/main/webapp/login.jsp to allow users to login.

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<html>
<head>
    <title>Login</title>
    <link rel="stylesheet" type="text/css" media="all"
          href="http://demo.appfuse.org/appfuse-struts/styles/simplicity/theme.css"/>
    <style type="text/css">
        h1 {
            margin-left: -300px;
            margin-top: 50px
        }
    </style>
</head>
<body>
<h1>Login</h1>

<form method="post" id="loginForm" action="<c:url value='/j_security_check'/>">
    <fieldset style="padding-bottom: 0">
        <ul>
            <c:if test="${param.error != null}">
                <li class="error">
                    ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
                </li>
            </c:if>
            <li>
                <label for="j_username" class="required desc">
                    Username <span class="req">*</span>
                </label>
                <input type="text" class="text medium" name="j_username"
                       id="j_username" tabindex="1"/>
            </li>

            <li>
                <label for="j_password" class="required desc">
                    Password <span class="req">*</span>
                </label>
                <input type="password" class="text medium" name="j_password"
                       id="j_password" tabindex="2"/>
            </li>
            <li>
                <input type="submit" class="button" name="login" value="Login"
                       tabindex="3"/>
            </li>
        </ul>
    </fieldset>
</form>
</body>
</html>

All the changes described in the above section are necessary to implement OAuth if you create a project with AppFuse WS 2.1. It may seem like a lot of code, but I was able to copy/paste and get it all working in an app in under 5 minutes. Hopefully you can do the same. I'm also considering adding it by default to the next version of AppFuse. Now let's look at integrating OAuth into a client to authenticate and retrieve data from this application.

Authenticate and Retrieve Data with Client
I originally thought my GWT OAuth application would provide a nice client. However, after 30 minutes of trying to get GWT 1.7.1 and the GWT Maven plugin (1.1) working with my 64-bit Java 6 JDK on OS X, I gave up. So I opted to use the Ajax Login application I've been using in my recent security tutorials.

In this example, I used OAuth2RestTemplate from Spring Security OAuth. While this works, and works well, I'd still like to get things working with GWT (or jQuery) to demonstrate how to do it from a pure client-side perspective.

To begin, I got the latest source of Ajax Login from GitHub (as of this morning) and made some changes. First of all, I added the Spring Security OAuth dependencies to pom.xml:

<repository>
    <id>spring-milestone</id>
    <url>http://s3.amazonaws.com/maven.springframework.org/milestone</url>
</repository>
...
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth</artifactId>
    <version>1.0.0.M3</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Then I modified src/main/webapp/WEB-INF/security.xml and added an OAuth Token Service and defined the location of the OAuth server.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
              http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
              http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">

...
    <oauth:client token-services-ref="oauth2TokenServices"/>

    <beans:bean id="oauth2TokenServices"
                class="org.springframework.security.oauth2.consumer.token.InMemoryOAuth2ClientTokenServices"/>

    <oauth:resource id="appfuse" type="authorization_code" clientId="ajax-login"
                    accessTokenUri="http://localhost:9000/appfuse-oauth/oauth/authorize"
                    userAuthorizationUri="http://localhost:9000/appfuse-oauth/oauth/user/authorize"/>

Next, I created a Controller that uses OAuth2RestTemplate to make the request and get the data from the AppFuse OAuth application's API. I created src/main/java/org/appfuse/examples/webapp/oauth/UsersApiController.java and filled it with the following code:

package org.appfuse.examples.webapp.oauth;

import org.appfuse.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.consumer.*;
import org.springframework.security.oauth2.consumer.token.OAuth2ClientTokenServices;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

@RequestMapping("/appfuse/users")
@Controller
public class UsersApiController {

    private OAuth2RestTemplate apiRestTemplate;
    @Autowired
    private OAuth2ClientTokenServices tokenServices;

    private static final String REMOTE_DATA_URL = "http://localhost:9000/appfuse-oauth/api/users";

    @Autowired
    public UsersApiController(OAuth2ProtectedResourceDetails resourceDetails) {
        this.apiRestTemplate = new OAuth2RestTemplate(resourceDetails);
    }

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<User> getUsers() {
        try {
            List users = apiRestTemplate.getForObject(REMOTE_DATA_URL, List.class);
            return new ArrayList<User>(users);
        } catch (InvalidTokenException badToken) {
            //we've got a bad token, probably because it's expired.
            OAuth2ProtectedResourceDetails resource = apiRestTemplate.getResource();
            OAuth2SecurityContext context = OAuth2SecurityContextHolder.getContext();
            if (context != null) {
                // this one is kind of a hack for this application
                // the problem is that the sparklr photos page doesn't remove the 'code=' request parameter.
                ((OAuth2SecurityContextImpl) context).setVerificationCode(null);
            }
            //clear any stored access tokens...
            tokenServices.removeToken(SecurityContextHolder.getContext().getAuthentication(), resource);
            //go get a new access token...
            throw new OAuth2AccessTokenRequiredException(resource);
        }
    }
}

At this point, I thought everything would work and I spent quite some time banging my head against the wall when it didn't. As I was composing an email to the Enunciate users mailing list, I realized the issue. It appeared to be working, but from the server side, and the redirect back to the client was not happening. The Ajax Login app uses UrlRewriteFilter (for pretty URLs) to redirect from /app/* to /$1 and this redirect was losing the code parameter in the URL.

<rule>
    <from>/app/**</from>
    <to last="true" type="redirect">%{context-path}/$1</to>
</rule>

To fix this, I added use-query-string="true" to the root element in src/main/webapp/WEB-INF/urlrewrite.xml:

<urlrewrite default-match-type="wildcard" use-query-string="true">

After making all these changes, I ran mvn jetty:run on both apps and opened http://localhost:8080/appfuse/users in my browser. It all worked and a smile crept across my face. I've checked in the client changes into ajax-login on GitHub and the appfuse-oauth example into AppFuse Demos on Google Code. If you'd like to see this example in action, I'd encourage you to checkout both projects and let me know if you find any issues.

Posted in Java at Jul 05 2011, 10:56:48 AM MDT 4 Comments

Java Web Application Security - Part II: Spring Security Login Demo

Last week, I wrote a tutorial on how to implement Security in Java EE 6. This week, I'd like to show you how to implement the same features using Spring Security. Before I begin, I'd like to explain my reason for writing this article.

Last month, I presented a talk on Java Web Application Security at the Utah JUG (UJUG). As part of that presentation, I did a number of demos about how to implement security with Java EE 6, Spring Security and Apache Shiro. I told the audience that I would post the presentation and was planning on recording screencasts of the various demos so the online version of the presentation would make more sense.

Today, I've finished the second screencast showing how to implement security with Spring Security. Below is the presentation (with the screencast embedded on slide 16) as well as a step-by-step tutorial.


Spring Security Login Tutorial

Download and Run the Application
To begin, download the application you'll be implementing security in. This app is a stripped-down version of the Ajax Login application I wrote for my article on Implementing Ajax Authentication using jQuery, Spring Security and HTTPS. You'll need Java 6 and Maven installed to run the app. Run it using mvn jetty:run and open http://localhost:8080 in your browser. You'll see it's a simple CRUD application for users and there's no login required to add or delete users.

Implement Basic Authentication
The first step is to protect the list screen so people have to login to view users. To do this, you'll need to create a Spring context file that contains Spring Security's configuration. Create src/main/webapp/WEB-INF/security.xml and populate it with the contents below:

  <?xml version="1.0" encoding="UTF-8"?>
  <beans:beans xmlns="http://www.springframework.org/schema/security"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:beans="http://www.springframework.org/schema/beans"
               xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

      <!-- New in Spring Security 3.1 -->
      <!-- <http pattern="/css/**" security="none"/> -->

      <http auto-config="true">
          <intercept-url pattern="/app/users" access="ROLE_USER,ROLE_ADMIN"/>
          <http-basic/>
      </http>

      <authentication-manager alias="authenticationManager">
          <authentication-provider>
              <password-encoder hash="sha"/>
              <user-service>
                  <user name="user" password="12dea96fec20593566ab75692c9949596833adc9" authorities="ROLE_USER"/>
                  <user name="admin" password="d033e22ae348aeb5660fc2140aec35850c4da997" authorities="ROLE_ADMIN"/>
              </user-service>
          </authentication-provider>
      </authentication-manager>

      <!-- Override userSecurityAdvice bean in appfuse-service to allow any role to update a user. -->
      <beans:bean id="userSecurityAdvice" class="org.appfuse.examples.webapp.security.UserSecurityAdvice"/>
  </beans:beans>

The last bean, userSecurityAdvice, is an aspect that's needed to override some behavior in AppFuse. You won't need this normally when implementing Spring Security.

Next, open src/main/webapp/WEB-INF/web.xml and add Spring's DelegatingFilterProxy:

<filter>
    <filter-name>securityFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>springSecurityFilterChain</param-value>
    </init-param>
</filter>

And add its filter-mapping just after the rewriteFilter in the filter-mappings section (order is important!):

<filter-mapping>
    <filter-name>rewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>securityFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

You don't need to add any dependencies in your pom.xml is because this project depends on AppFuse, which already contains these dependencies.

At this point, if you restart Jetty (Ctrl+C and jetty:run again), you should be prompted to login when you click on the "Users" tab. Enter admin/admin to login. Spring Security is a bit easier to configure than Java EE 6 out-of-the-box, mostly because it doesn't require you to configure your container.

After logging in, you can try to logout by clicking the "Logout" link in the top-right corner. This calls a LogoutController with the following code that logs the user out.

public void logout(HttpServletResponse response) throws ServletException, IOException {
    request.getSession().invalidate();
    response.sendRedirect(request.getContextPath()); 
}

NOTE: Spring Security has a way to configure "logout" to match a URL and get rid of a class like LogoutController. Since it was already in the project, I don't cover that in this tutorial.

You'll notice that clicking this link doesn't log you out, even though the session is invalidated. The only way to logout with basic authentication is to close the browser. In order to get the ability to logout, as well as to have more control over the look-and-feel of the login, you can implement form-based authentication. Before you implement form-based authentication, I'd like to show you how easy it is to force SSL with Spring Security.

Force SSL
Spring Security allows you to switch between secure (https) and non-secure (http) protocols using a simple requires-channel attribute on the <intercept-url> element. Possible values are "http", "https" and "any". Add requires-channel="https" to your security.xml file:

<intercept-url pattern="/app/users" access="ROLE_USER,ROLE_ADMIN" requires-channel="https"/>

In order for this to work, you have to configure Jetty to listen on an SSL port. Add the following just after the jetty-maven-plugin's </webAppConfig> element in your pom.xml:

<connectors>
    <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <forwarded>true</forwarded>
        <port>8080</port>
    </connector>
    <connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
        <forwarded>true</forwarded>
        <port>8443</port>
        <maxIdleTime>60000</maxIdleTime>
        <keystore>${project.build.directory}/ssl.keystore</keystore>
        <password>appfuse</password>
        <keyPassword>appfuse</keyPassword>
    </connector>
</connectors>

The keystore must be generated for Jetty to start successfully, so add the keytool-maven-plugin just above the jetty-maven-plugin in pom.xml.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>keytool-maven-plugin</artifactId>
    <version>1.0</version>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <id>clean</id>
            <goals>
                <goal>clean</goal>
            </goals>
        </execution>
        <execution>
            <phase>generate-resources</phase>
            <id>genkey</id>
            <goals>
                <goal>genkey</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <keystore>${project.build.directory}/ssl.keystore</keystore>
        <dname>cn=localhost</dname>
        <keypass>appfuse</keypass>
        <storepass>appfuse</storepass>
        <alias>appfuse</alias>
        <keyalg>RSA</keyalg>
    </configuration>
</plugin>

Now if you restart Jetty, go to http://localhost:8080 and click on the "Users" tab, you'll be prompted to accept the Untrusted Certificate and then redirected to https://localhost:8443/users after logging in. This is an improvement on Java EE's user-data-constraint for two reasons:

  • You can switch between http and https protocols. With Java EE, you can only force https. You have to write a custom filter to switch back to http.
  • Redirecting to https actually works. With Java EE (on Jetty at least), a 403 is returned instead of redirecting the request.

Now let's look at how to have more control over the look-and-feel of the login screen, as well as how to make logout work with form-based authentication.

Implement Form-based Authentication
To change from basic to form-based authentication, you simply have to add a <form-login> element in security.xml's <http> element:

<http auto-config="true">
    <intercept-url pattern="/app/users" access="ROLE_USER,ROLE_ADMIN" requires-channel="https"/>
    <form-login login-page="/login" authentication-failure-url="/login?error=true"
                login-processing-url="/j_security_check"/>
    <http-basic/>
</http>

You can leave the <http-basic> element since Spring Security is smart enough to serve up the form for browsers and use Basic Authentication for clients such as web services. The login.jsp page (that /login forwards to) already exists in the project, in the src/main/webapp directory. The forwarding is done by the UrlRewriteFilter with the following configuration in src/main/webapp/WEB-INF/urlrewrite.xml.

<rule>
    <from>/login</from>
    <to>/login.jsp</to>
</rule>

This JSP has 3 important elements: 1) a form that submits to "/j_security_check", 2) an input element named "j_username" and 3) an input element named "j_password". If you restart Jetty, you'll now be prompted to login with this JSP instead of the basic authentication dialog.

Add Remember Me
Remember Me is a feature you see in many web applications today. It's usually a checkbox on the login form that allows you to auto-login the next time you visit a site. This feature doesn't exist in Java EE security, but it does exist in Spring Security. To enable it, add the following just below <form-login> in security.xml:

<remember-me user-service-ref="userDao" key="e37f4b31-0c45-11dd-bd0b-0800200c9a66"/>

Next, open src/main/webapp/login.jsp and change the name of the "remember me" checkbox to be _spring_security_remember_me:

<input type="checkbox" name="_spring_security_remember_me" id="rememberMe"/>

After making these changes, you should be able to restart Jetty, go to http://localhost:8080/users, enter admin/adminjdbc, check the Remember Me checkbox and login. Then close your browser, and repeat the process. This time, you won't be prompted to login. For more information on this feature, see Spring Security's Remember Me documentation.

While storing usernames and passwords in a file is convenient for demos, it's not very real-world-ish. The next section shows you how to configure Spring Security to use a database for its user store.

Store Users in a Database
To store your users in a database instead of file, you'll need to add a user-service-ref attribute to the <authentication-provider> element. You can also delete the <user-service> element.

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="userDao">
        <password-encoder hash="sha"/>
    </authentication-provider>
</authentication-manager>

The "userDao" bean is provided by AppFuse and its UserDaoHibernate.java class. This class implements Spring Security's UserDetailsService interface. With Java EE, I had to configure a database connection and make sure the JDBC Driver was in my container's classpath. With Spring Security, you can talk to the database you already have configured in your application.

Of course, you could do this with Java EE too. One thing I neglected to show in my last tutorial was that 1) the app uses H2 and 2) I had to configure Java EE's database to be MySQL. This was because when I tried to access my H2 instance, I got an error about two threads trying to access it at once.
2011-05-13 08:47:29.081:WARN::UserRealm Java EE Login could not connect to database; will try later
org.h2.jdbc.JdbcSQLException: Database may be already in use: "Locked by another process". 
        Possible solutions: close all other connection(s); use the server mode [90020-154]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
	at org.h2.message.DbException.get(DbException.java:167)
	at org.h2.message.DbException.get(DbException.java:144)
	at org.h2.store.FileLock.getExceptionAlreadyInUse(FileLock.java:443)
	at org.h2.store.FileLock.lockFile(FileLock.java:338)
	at org.h2.store.FileLock.lock(FileLock.java:134)
	at org.h2.engine.Database.open(Database.java:535)
	at org.h2.engine.Database.openDatabase(Database.java:218)

The password for the "admin" user is configured in src/test/resources/sample-data.xml and it's loaded by DbUnit before the application starts. You can view your pom.xml and the dbunit-maven-plugin's configuration if you're interested in learning how this is done. The password is currently configured to "adminjdbc", but you can reset it by generating a new password and modifying sample-data.xml.

Now if you restart Jetty, you should be able to login with admin/adminjdbc and view the list of users.

Summary
In this tutorial, you learned how to implement authentication using Spring Security 3.0.5. In addition to the basic XML configuration, Spring Security also provides a AOP support and annotations you can use to secure methods. It also has many more features than standard Java EE Security. In my opinion, it's the most mature security framework we have in Java today. Currently, I think its reference documentation is the best place to learn more.

There are a few limitations I found with Spring Security:

  • The authentication mechanism (file, database, ldap, etc.) is contained in the WAR
  • Securing methods only works on Spring beans
  • Remember Me doesn't work in my screencast (because I forgot to rename the checkbox in login.jsp)

Of course, you can configure Spring to load its configuration from outside the WAR (e.g. a file or JNDI), but it's not as easy as including the configuration in your app.

In the next couple weeks, I'll post Part III of this series, where I'll show you how to implement this same set of features using Apache Shiro. In the meantime, please let me know if you have any questions.

I created the screencasts with Camtasia. For small screens, and embedding in the presentation, I created it at 50% and used the SmartFocus feature to zoom in and out during the demo. For larger screens, I published another screencast at 100%, in HD. If you have a preference for which screencast is better, I'd love to hear about it.

Posted in Java at May 13 2011, 09:20:51 AM MDT 10 Comments

Trim Spaces in your JSP's HTML Redux

Since my last post on trimming whitespace in JSPs seems to be a popular topic, I figured it appropriate to note that JSP 2.1 supports a new trimWhitespace directive.

<%@ page trimDirectiveWhitespaces="true" %>

If you're using a Servlet 2.5 XSD, you can also do this in your web.xml:

    <jsp-config>
      <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <trim-directive-whitespaces>true</trim-directive-whitespaces>
      </jsp-property-group>
    </jsp-config>

A Servlet 2.5 XSD seems to be the following:

<web-app
    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/web-app_2_5.xsd"
    metadata-complete="false"
    version="2.5">

To learn more about this feature, view Summary of New Features in JSP 2.1 Technology and search for "TrimWhiteSpace". It'd be nice if there was anchors in this article for a direct link, but I couldn't find any.

Now I just wish JSP's EL had an xmlEscape="true" flag to escape XML in printed variables. Freemarker supports this.

Hat tip to Kerem and Krishna's Unified Expression Language for JSP and JSF article.

Posted in Java at Aug 01 2007, 05:01:25 PM MDT 10 Comments

Integrating Struts 2 + JSF + Facelets

What if you didn't have to choose between a request-based framework and a component-based framework? What if you could use them together and use request-based for some pages and component-based for others? This is the functionality that the Struts 2 JSF Plugin provides.

To be fair, the JSF-Spring project says it does the same thing for Spring MVC + JSF, but there doesn't appear to be any documentation.

I did some prototyping of Struts 2 + JSF and discovered that it does indeed work. I also discovered that there's no documentation on integrating it with Facelets. Luckily, it's pretty easy to do - hence my reason for writing this entry. You might ask why I want to use Facelets when JSF 1.2 supports JSP fairly well? My reason is because JSP 2.1 hijacks #{}, which Struts 2's OGNL uses for some expressions. Because of this, I want to be able to run on a JSP 2.0 container until a workaround comes along. Sun's JSF 1.2 RI can run on a JSP 2.0 container, while MyFaces 2.1 cannot (at least in my experience).

There's two ways to get Struts 2 + JSF + Facelets working:

  • Create a WEB-INF/faces-config.xml file and override the default view-handler:
    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config 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/web-facesconfig_1_2.xsd"
        version="1.2">
    
        <application>
            <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
        </application>
    </faces-config> 
    
  • The 2nd way is to use Ajax4JSF and declare the view-handler in your web.xml (allowing you to get rid of faces-config.xml):
    <context-param>
        <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
        <param-value>com.sun.facelets.FaceletViewHandler</param-value>
    </context-param>
    
NOTE: You have to use 2nd method if you want to use Ajax4JSF. It won't read the view-handler from faces-config.xml.

If you're using SiteMesh, you may have to add another <parser> element to your sitemesh.xml to get Facelets pages decorated:

<parser content-type="application/xhtml+xml"
    class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/> 

Thanks to Laurie Harper for his assistance figuring this stuff out.

Now you might ask - why would you want to do this? For one, Struts 2 has a better navigation model (IMO) than JSF. Also, if developers want to use JSF and think it's a better way for a certain module - let them go to it!

Posted in Java at Jul 26 2007, 12:13:59 PM MDT 18 Comments

The Security Annotation Framework

Spotted on the Acegi Security mailing list several weeks ago:

A few weeks ago, I started an open source project (Security Annotation Framework) which addresses annotation-based, instance-level access control for Spring applications. It is also based on Spring 2.0's extensible XML authoring features. You can find more info at

http://sourceforge.net/projects/safr and http://safr.sourceforge.net

The framework was created during a project in 2006 and is now available under the Apache 2.0 license. It's a generic framework focused on processing security annotations on Spring beans as well as domain objects (which typically aren't managed by a Spring application context) and can be used to enforce access decisions for domain object instances. It can be used with any authorization provider and is not specific to Acegi. However, I plan to include an example how to use the SAF with Acegi authorization soon. Furthermore, it supports inheritance of annotations from base classes and interfaces.

What do you think about SAF? Are annotations a better way of implementing ACLs on domain objects?

Posted in Java at May 24 2007, 12:42:35 PM MDT 1 Comment

Upgrading to MyFaces 1.1.5 and Spring 2.x + Resin 3.x + Cargo

This week, I encountered a few issues with some open source software that I hadn't seen before. Furthermore, it was difficult to find the problems' solutions via Google, so I figured I'd blog about them and make life less painful for the next person.

Upgrading MyFaces to 1.1.5
The first issue I experienced was when I tried to upgrade from MyFaces 1.1.4 to 1.1.5. After upgrading, my Canoo WebTests failed on some pages because the page kept redirecting to itself instead of submitting a form and properly processing the result. The solution was found with a simple e-mail to the project's mailing list. If you have a view template that auto-submits to a backing bean, you need to change "_link_hidden_" to "_idcl". Apparently, this change was made to be more similar to the JSF RI. Of course, this hack wouldn't be necessary if JSF would simply allow you to call a method from a URL without going to a view page first.

Spring 2.0's RequestContextListener has issues on Resin and WebSphere
Spring 2.0.2 has a bug where its RequestContextListener throws a NPE on WebSphere 6.0 and Resin 3.x. This is fixed in Spring 2.0.3.

Making Resin 3.x XSD-aware when using Cargo
By default, Resin 3.x doesn't ship with an XSD-aware parser turned on. This means that if you're using Spring 2.0 XSDs, you will need to set some configuration options on Resin. I don't know why Resin doesn't ship with these on by default, but it doesn't. This presents a problem if you're using Cargo to download and install Resin. The good news is you can configure Cargo to set system properties and turn Resin's XSD parser on. Adding the following to the <container> element in the Cargo plugin's configuration to solve the problem.

<!-- Make Resin aware of Spring 2.0 XSDs -->
<systemProperties>
    <javax.xml.parsers.DocumentBuilderFactory>
        org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
    </javax.xml.parsers.DocumentBuilderFactory>
    <javax.xml.parsers.SAXParserFactory>
        org.apache.xerces.jaxp.SAXParserFactoryImpl
     </javax.xml.parsers.SAXParserFactory>
</systemProperties>

Resin and Cargo
Finally, Cargo 0.2 throws a NoClassDefFoundError when shutting down Resin 3.0.23 and doesn't work at all with Resin 3.1.0. What does this mean? It means Cargo works great with Tomcat and JBoss, but not so good with Resin 3.x, Jetty 6.x or Geronimo 1.1.

It's too bad, Cargo really is a great project idea. Maybe the container developers should get involved to help it support all the latest versions?

Posted in Java at Feb 24 2007, 04:33:20 PM MST 1 Comment

[Microsoft] Day 1 Morning

"An open and honest dialog" - that's what the goal of this shindig is. Most of these sessions aren't really interesting to me. If there's APIs I can talk to, I'm cool with that, but as far as SQL Server 2005 and Windows Architecture ... I'm not interested. The thing I'm looking forward to today more than anything is meeting Scoble.

Most of the folks in this room seem to be community leaders, i.e. JUG Founders and architects. There's also a fair amount of "Developer Evangelists" in the room. Probably half the room is MS people. I wonder what the hell a Developer Evangelist does? Do they write any code? I'm guessing there's no MS coders in the room.

Michael Howard - Improving Security at Microsoft by changing the process

Michael Howard is the co-author of the "Writing Secure Code" book that we all received this morning. He's writing a new book called the "19 Deadly Sins of Software Security" - which apparently covers everything: Windows, Linux, OS X, Java, JSP, MySQL, Oracle, etc. Sounds like a pretty good book - it's got some open-source guy as a co-author too. It's a McGraw Hill book and should be short-n-sweet at 300 pages. Michael is the Senior Security Program Engineer and sounds like a champion of the "Trustworthy Computing" mantra here at Microsoft.

zone-h.org tracks the number of web server attacks. Michael is talking about the fact that IIS 6.0 has had one security bug in 2 years, while Apache 1.3 has 13 and Apache 2.0 has had over 20. "Apache has more security bugs than IIS."

Everyone has security bugs, we're the only ones doing something about it.

Application compatibility is now a #2 priority at Microsoft, Security is #1. They're willing to break application compatibility, a.k.a. "app compat", for the sake of security.

Threat Modeling - they do a lot of research on skills vs. motivations. They're basically trying to understand not only how, but why hackers attack.

OK, this is a pretty boring talk - mostly because it doesn't interest me. There's a lot of talk about security in "Whidbey", which is the next version of Visual Studio.NET. Apparently, it's now got some tools to detect security issues and memory leaks. My boredom has caused me to start working on AppFuse, and to try out the USB Flash Memory Drive they gave us. It's kinda funny - the box it came in has a link to where you can download the drivers for Windows 98/SE. No driver is needed for ME/2000/XP. I also discovered that it works great on the Mac. Cool - too bad it's pretty much useless if you're always online like I am.

Heh, shortly after writing the above, I yanked out the device and it killed both Keynote and BBEdit. It's definitely a useless device!

Don Box - Microsoft Messaging Futures Using Indigo

Don is taking an interesting approach to his presentation - and typing it all in notepad. He wants us to tell him why we think MSFT sucks. Don works on the XML messaging stack. Specifically, he's an architect on Indigo and he worked on the WS-* specs. An audience member puts a stop to the typing because he's legally blind and can't read anything. Here comes the talking. How does Microsoft suck?

Audience feedback:

  • Community Involvement sucks
  • Need to do security by default
  • COM+ isms not there - transactions more mature in J2EE
  • Does MS believe in managed code?
  • 2 year platform cycles, re-invention w/ every release
  • Dependency hairball - shouldn't have to buy other products to make simple things work
  • Dependency Injection, IoC, ORM

I brought up the fact that MSFT crushes or buys their competition more often then not. Don spent some time answering this question, defending MSFT a bit, but also saying that we're in a new decade now and it's a very competitive industry. For the record, I don't really believe MSFT is the "Evil Empire" like many hard-core Linux and open-source guys. I have quite a few MSFT certifications, but I've found most of them useless in my career - except that I can easily troubleshoot and fix most of the issues I have on Windows. I use Windows and prefer it over OS X for the most part, but that's because I'm more efficient using Windows, and because my Windows box is much faster than my PowerBook. ;-)

Don reminds me of a good friend of mine - Chad Shoup - but he's about 10 years older. For those of you who know Chad, you know he's fun to listen to. I don't have much interest in the talk (I don't even know what Indigo is), but it's an enjoyable talk - mainly because he's enthusiastic about what he's talking about - and he's walking around the room, keeping the audience involved.

RelaxNG is better than XSD. The primary goal of Indigo is to satisfy the customers and consolidating the choices in .NET so that choices are easy and explicitly - instead of having a number of different products that do the same thing. They don't plan on taking choices away - they just plan on making the choice easy and explicit. If you're working with .NET, there might actually appear to be an architect behind it all.

Don goes on to address all the audience feedback and explain MSFT's position and what they're doing to address this. Sorry, I tuned out as I wasn't that interested. The one interesting quote I got out of this session is "I believe we're going to be more than competitive in O/R Mapping. Soon."

Richard Monson-Haefel asks "Is there a place for AOP in .NET or is it too sophisticated for your developers." Don's take is "My development platform should allow me to write code w/ a couple of beers in me." He ragged a bit on Java developers and said their main problem is they think they're smarter than they are. He also said that if he could change on thing at MSFT, it would be that Ruby becomes the language of choice.

Break time: yogurt and granola. I got a picture with Don and will post that as soon as I find a cable. I'm also going to see what this "Double Strength, Double Size, Rockstar Energy Drink" is all about. It sounds poisonous, but it's likely to give me a wicked buzz or make me throw up. Seems like a good experiment.

Looking outside, it's raining now - which seems appropriate now that we're going to have a Programming Language Design Panel. The rain goes with my depression that I have to sit through this session. I doubt it'll be of any interest to me.

Programming Language Design Panel: Jim Miller (CLR Architect), Herb Sutter (C++ Architect), Jim Hugunin (Lead for IronPython and dynamic languages on CLR)

Jim Miller: The five programming languages that Microsoft ships: C#, VB.NET, C++, J# and JScript. Generics are now a part of the run-time environment. Closures and light-weight code-generation will also be available.

Herb Sutter: Only guy on the panel that cares about managed and native code.

C# Guy: C# 2.0 features: Generics - code looks a lot like Java, but implementation is very different in CLR. Closures so you can pass methods as arguments. Iterators - lazy enumeration of collections like Python and Ruby. Partial types or structured include files - multiple files make up one class (good for code generation).

Jim Hugunin: Used to be a Java Developer, working with AspectJ and other dynamic languages. He wanted to see why .NET was such a horrible platform for dynamic languages. A year later, he found himself working for Microsoft. He's found that .NET is a good platform for dynamic languages (of course, right?). His current job is getting IronPython to 1.0.

Dion asks about Ruby on .NET and about AOP in .NET. Jim doesn't know of any major projects that are addressing Ruby on .NET. C# guy says that we have a lot we can learn from dynamic languages and thinks the best thing is to allow less typing (i.e. declare type once) in strongly-typed languages like C# and Java. As far as AOP, the C# guy is still in the wait-and-see mode.

Rockstar Energy Drink Status: I made it about 1/3 of the way through it before the stomach ache kicked in. Now I'm jittery and nauseous... <great/>

IronPython will likely be an open-source project b/c the Python Community will probably reject it otherwise.

Will Java 5.0 code be able to easily port into J#? The panel doesn't know and thinks it's more of a legal question. J# currently supports JDK 1.4 syntax and they don't think there current license allows supporting JDK 5.0.

Mono - they've been taking a wait-and-see approach to see the commercial uptake on it. So far, they haven't seen a whole lot of commercial interest in Mono, nor any licensing requests from Novell.

Posted in Java at Mar 17 2005, 12:29:00 AM MST 4 Comments