Monday, January 21, 2013

Writing REST services in Java: Part 4 Facebook Authentication

Previous Post : Part Three: Email Verification
Get the Code: https://github.com/iainporter/rest-java

This post will cover OAuth Authentication with Facebook. Most REST applications provide a user with a choice of signing up with their email address and password or to delegate to a third-party security provider such as Facebook, Twitter, Google, etc. The solution in the rest-java application uses Javascript libraries on the client side for the oauth dance and Spring Social on the server for communicating with the Facebook social graph API.

 Client Code

Whether the client is a web page or a mobile device the desired end result is the same: to get an access token from the Facebook API.

The client code in scr/main/webapp/index.html:

window.fbAsyncInit = function() {
     FB.init({
       appId      : '133718006790561', // App ID
       status     : true, // check login status
       cookie     : true, // enable cookies to allow the server to access the session
       xfbml      : true  // parse XFBML
      });

      $('.fb').on('click', function () {

      FB.login(function(response) {
         console.log(response)
         if (response.authResponse) {
            javaRest.user.loginSocial(response.authResponse.accessToken, 
               function (error) {
               if (error)
                  console.log(error)
               else
                  window.location = 'dashboard.html'
               })
               console.log('Welcome!  Fetching your information.... ');
               FB.api('/me', function(response) {
                   console.log('Good to see you, ' + response.name + '.');
               });
          } else {
             console.log('User cancelled login or did not fully authorize.');
          }
       });

    })

 };
        
// Load the SDK Asynchronously
(function(d){
    var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
    if (d.getElementById(id)) {return;}
    js = d.createElement('script'); js.id = id; js.async = true;
    js.src = "//connect.facebook.net/en_US/all.js";
    ref.parentNode.insertBefore(js, ref);
}(document));
When registering the app with Facebook we insert the appId in line 03.
Facebook makes a callback with an authorization popup window.
The user accepts and we receive back an access token which we then use to call the API (line 14).

Server API Endpoint


Once the client has an access token they then call the server API which has an endpoint of:

user/login/<providerId>

In this case the providerId is facebook

The json payload is simply {"accessToken":"<the User's Facebook access token>"}

On the server side we want to achieve three things:

1. Access the user's Facebook profile and persist some relevant details
2. Match the profile up with an existing user account or else create a new one
3. Return an Authenticated User Token for API access so that we can treat Facebook logins the same as an email login

User Resource


    @PermitAll
    @Path("login/{providerId}")
    @POST
    public Response socialLogin(@PathParam("providerId") String providerId, OAuth2Request request) {
        OAuth2ConnectionFactory<?> connectionFactory = (OAuth2ConnectionFactory<?>) connectionFactoryLocator.getConnectionFactory(providerId);
        Connection<?> connection = connectionFactory.createConnection(new AccessGrant(request.getAccessToken()));
        AuthenticatedUserToken token = userService.socialLogin(connection);
        return getLoginResponse(token);
    }
We get a ConnectionFactory using the ConnectionFactoryLocator that was configured in SocialConfig.java
The factory class then creates a connection using the access token and the service method is called to login the user.

SocialConfig.java

@Configuration
public class SocialConfig {

    @Autowired
    ApplicationConfig config;

    @Autowired
    SocialUserRepository socialUserRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    TextEncryptor textEncryptor;

    @Bean
    public ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
        registry.addConnectionFactory(new FacebookConnectionFactory(
            config.getFacebookClientId(),
            config.getFacebookClientSecret()));
        return registry;
    }

    @Bean
    public UsersConnectionRepository usersConnectionRepository() {
        JpaUsersConnectionRepository usersConnectionRepository = new 
                JpaUsersConnectionRepository(socialUserRepository, userRepository,
                connectionFactoryLocator(), textEncryptor);

        return usersConnectionRepository;
    }
}

Social User Domain Model


A User has a many-to-one relationship with SocialUser instances. In the SocialUser model we need to capture several important pieces of information such as:

  • providerId - the security implementation provider (facebook)
  • providerUserId - the identifier within the Facebook universe
  • accessToken - the key needed to access the user's profile in Facebook (encrypted in the DB)
We can also capture other useful information such as profileImage, profileUrl, displayName, etc.

Note that we cannot guarantee to get an email address.

User Service


The implementation method for social login is:

    @Transactional
    public AuthenticatedUserToken socialLogin(Connection<?> connection) {

        List<String> userUuids = jpaUsersConnectionRepository.findUserIdsWithConnection(connection);
        if(userUuids.size() == 0) {
            throw new AuthenticationException();
        }
        User user = userRepository.findByUuid(userUuids.get(0)); //take the first one if there are multiple userIds for this provider Connection
        if (user == null) {
            throw new AuthenticationException();
        }
        updateUserFromProfile(connection, user);
        return new AuthenticatedUserToken(user.getUuid().toString(), createAuthorizationToken(user).getToken());
    }


The JpaUsersConnectionRepository is used to connect to Facebook and retrieve the User's profile. It then matches it up to an existing user or else creates a new one if this is the first login attempt.
Once we have an API User we then create or update a SocialUser profile and associate it with the User.

JpaUsersConnectionRepository


The relevant method:
/**
* Find User with the Connection profile (providerId and providerUserId)
* If this is the first connection attempt there will be nor User so create one and
* persist the Connection information
* In reality there will only be one User associated with the Connection
*
* @param connection
* @return List of User Ids (see User.getUuid())
*/
public List<String> findUserIdsWithConnection(Connection<?> connection) {
    List<String> userIds = new ArrayList<String>();
    ConnectionKey key = connection.getKey();
    List<SocialUser> users = 
              socialUserRepository.findByProviderIdAndProviderUserId
             (key.getProviderId(), key.getProviderUserId());
    if (!users.isEmpty()) {
        for (SocialUser user : users) {
            userIds.add(user.getUser().getUuid().toString());
        }
        return userIds;
    }
//First time connected so create a User account or find one that is already 
//created with the email address
    User user = findUserFromSocialProfile(connection);
    String userId;
    if(user == null) {
       userId = userService.createUser(Role.authenticated).getId();
    } else {
       userId = user.getUuid().toString();
    }
    //persist the Connection
    createConnectionRepository(userId).addConnection(connection);
    userIds.add(userId);
    return userIds;
}

private User findUserFromSocialProfile(Connection connection) {
    User user = null;
    UserProfile profile = connection.fetchUserProfile();
    if(profile != null && StringUtils.hasText(profile.getEmail())) {
        user = userRepository.findByEmailAddress(profile.getEmail());
    }
    return user;
}

Testing the API



Step 1. Create an application on Facebook and if you want to test it locally set the site url to http://localhost:8080/java-rest
















Step 2. Insert your App Id and App Secret in src/main/resources/app.properties
Step 3. Insert your appId in to the relevant place in the javascript in src/main/webapp/index.html and src/main/webapp/signup.html
Step 4. Start the application by running :
gradle tomcatRun


Step 5. In a browser window request http://localhost:8080/java-rest/index.html

You should be able to login with your Facebook credentials

This can easily be extended to include other OAuth providers such as Twitter or Google
That wraps up this post.
In the next post I will cover the Lost Password API.

Monday, January 14, 2013

Writing REST Services in Java: Part 3 Email Verification

Previous Post : Part Two: User sign up and login  Next PostPart Four: Facebook Authentication  
Get the Code: https://github.com/iainporter/rest-java

In this post I'll discuss the process of verifying an email address after a new sign up. The logic flow for this is:

1. Generate a token for the user and persist it
2. Send an email with an embedded link that includes the token to the user
3. User clicks on the link which takes them to a static page
4. The static page calls the API passing the token
5. If the token is valid the user is set to verified
6. Response returned to the user

The Verification Token Service

This service is responsible for generating tokens, persisting them, communicating with the email services gateway and verifying returned tokens. The main properties of a VerificationToken are:
  • token - a UUID that is used to identify the token. It is Base64 encoded before being sent
  • expiryDate - time to live for the Token. Configured in app.properties
  • tokenType - enum (lostPassword, emailVerification, emailRegistration)
  • verified - has this token been verified

Looking at the method to send an Email Registration token:


    @Transactional
    public VerificationToken sendEmailRegistrationToken(String userId) {
        User user = ensureUserIsLoaded(userId);
        VerificationToken token = new VerificationToken(user,
                VerificationToken.VerificationTokenType.emailRegistration,
                config.getEmailRegistrationTokenExpiryTimeInMinutes());
        user.addVerificationToken(token);
        userRepository.save(user);
        emailServicesGateway.sendVerificationToken(new EmailServiceTokenModel(user,
                token, getConfig().getHostNameUrl()));
        return token;
    }

A new token is generated and persisted.
This token is then sent to the EmailServicesGateway where it is queued and the method returns, leaving the gateway to handle processing of the token asynchronously.

The Email Services Gateway

Email services are implemented with Spring Integration. The context file is at:

 src/main/resources/META-INF/spring/email-services-context.xml

The entry point is the Gateway component which routes to a queue-backed channel. This queue has a message store which in dev and local profiles uses a SimpleMessageStore. For staging and production a datasource is used. I'll cover setting up for production in a later post.

    <int:gateway id="emailServicesGateway" 
           service-interface="com.porterhead.rest.gateway.EmailServicesGateway"
           default-reply-timeout="3000">
    <int:method name="sendVerificationToken" 
            request-channel="emailVerificationRouterChannel" request-timeout="3000"/>
    </int:gateway>

    <int:channel id="emailVerificationRouterChannel">
        <int:queue capacity="1000" message-store="emailVerificationMessageStore"/>
    </int:channel>

A router polls the queue and routes to a channel based on the token type:


<int:router id="emailVerificationRouter" input-channel="emailVerificationRouterChannel"
   expression="payload.getTokenType()">
     <int:poller fixed-rate="2000">
        <int:transactional/>
     </int:poller>
     <int:mapping value="emailVerification" 
          channel="emailVerificationTokenSendChannel"/>
     <int:mapping value="emailRegistration"
          channel="emailRegistrationTokenSendChannel"/>
     <int:mapping value="lostPassword" channel="emailLostPasswordTokenSendChannel"/>
</int:router>

From there the appropriate MailSender method is invoked:


<int:service-activator id="emailRegistrationMailSenderService" 
      input-channel="emailRegistrationTokenSendChannel"
      output-channel="nullChannel" ref="mailSenderService"
      method="sendRegistrationEmail">
</int:service-activator>

The Mail Sender Service

The MailSenderService is responsible for constructing mime messages and sending them to their destination. Velocity is used as the template engine. The templates are in:

 src/main/resources/META-INF/velocity

The handler method:

    private EmailServiceTokenModel sendVerificationEmail(
                final EmailServiceTokenModel emailVerificationModel,
                final String emailSubject, 
                final String velocityModel, 
                final Map<String, String> resources) {
        MimeMessagePreparator preparator = new MimeMessagePreparator() {
            public void prepare(MimeMessage mimeMessage) throws Exception {
              MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,
              MimeMessageHelper.MULTIPART_MODE_RELATED, "UTF-8");
              messageHelper.setTo(emailVerificationModel.getEmailAddress());
              messageHelper.setFrom(config.getEmailFromAddress());
              messageHelper.setReplyTo(config.getEmailReplyToAddress());
              messageHelper.setSubject(emailSubject);
              Map model = new HashMap();
              model.put("model", emailVerificationModel);
              String text = 
                 VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, 
                 velocityModel, model);
                messageHelper.setText(new String(text.getBytes(), "UTF-8"), true);
                    for(String resourceIdentifier: resources.keySet()) {
                       addInlineResource(messageHelper, 
                       resources.get(resourceIdentifier),
                      resourceIdentifier);
                    }
              }
          };
        LOG.debug("Sending Verification Email to : {}",
                   emailVerificationModel.getEmailAddress());
        this.mailSender.send(preparator);
        return emailVerificationModel;
    }
The velocity templates are just bare-bones and will need to be customised to your needs.

Handling the Verification Request


The controller method passes through to the Verification Token Service

@PermitAll
    @Path("tokens/{token}")
    @POST
    public Response verifyToken(@PathParam("token") String token) {
        verificationTokenService.verify(token);
        return Response.ok().build();
    }


The service method to verify the token

    @Transactional
    public VerificationToken verify(String base64EncodedToken) {
        VerificationToken token = loadToken(base64EncodedToken);
        if (token.isVerified() || token.getUser().isVerified()) {
            throw new AlreadyVerifiedException();
        }
        token.setVerified(true);
        token.getUser().setVerified(true);
        userRepository.save(token.getUser());
        return token;
    }

    private VerificationToken loadToken(String base64EncodedToken) {
        Assert.notNull(base64EncodedToken);
        String rawToken = new String(Base64.decodeBase64(base64EncodedToken));
        VerificationToken token = tokenRepository.findByToken(rawToken);
        if (token == null) {
            throw new TokenNotFoundException();
        }
        if (token.hasExpired()) {
            throw new TokenHasExpiredException();
        }
        return token;
    }


The token is decoded and matched from the repository to an existing user. If that user has not already been verified then they are set to verified.

Testing the API

Before we can test the API the email service has to be configured. The context file containing the MailSender bean is at:

src/main/resources/META-INF/spring/email-template-context.xml

Choose a Mail Sender and insert the values into the mail properties. You can use a gmail or yahoo account for testing or there are several useful bulk mail sending options such as CritSend or MailJet.

<beans profile="production, staging">
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
      <!-- Email provider here-->
      <property name="host" value="<insert your Host name here>"/>
      <property name="port" value="<insert the port here>"/>
      <property name="username" value="<insert your username here>"/>
      <property name="password" value="<insert your password>"/>

        <property name="javaMailProperties">
          <props>
           <prop key="mail.debug">false</prop>
           <prop key="mail.smtp.auth">true</prop>
           <prop key="mail.smtp.starttls.enable">true</prop>
          </props>
        </property>
   </bean>

As you can see only the staging and production profiles are set up to send real mail. When running the dev and local profiles the MockJavaMailSender is invoked which simply stores the Mime messages in memory. To test out sending mail we can temporarily add the dev profile:

<beans profile="dev, production, staging">

and remove it from the other beans profile:

<beans profile="local">

Now start the application by executing:

gradle tomcatRun

Create a new user with the following curl statement (substituting in your real email address):

curl -v -H "Content-Type: application/json" -X POST -d '{"user":{"firstName":"Foo","lastName":"Bar","emailAddress":"<your email address>"}, "password":"password"}' http://localhost:8080/java-rest/user

You should then receive an email with the subject:
"Welcome to the Java-REST sample application"
This is configurable in app.properties although that will be covered in a later post.

You can either click on the link in the email and this will invoke a static page in the application that will forward on the token to another API call to verify the token. Alternatively you can copy the token in the link and construct a curl statement to do the same thing.

A sample curl to verify the token (substitute the token in your email):

curl -v -H "Content-Type: application/json"  -X POST -d  localhost http://localhost:8080/java-rest/verify/tokens/NjM1NjBkNTAtNjEwZi00N2I3LTk0MmQtYWMwMjVkY2MwNTc1

You should see this response:

< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json
< Content-Length: 0
< Date: Mon, 14 Jan 2013 08:30:18 GMT

If you execute the curl again you will receive a 409 response with a message saying the token has already been verified:

< HTTP/1.1 409 Conflict
< Server: Apache-Coyote/1.1
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Mon, 14 Jan 2013 08:30:58 GMT
{"errorCode":"40905","consumerMessage":"Already verified","applicationMessage":"The token has already been verified"}

What if a user changes their email address? In that case we should resend a verification email and have them verify their email address again. In the user/<id> PUT resource handler that is exactly what happens:

    @RolesAllowed({"authenticated"})
    @Path("{userId}")
    @PUT
    public Response updateUser(@Context SecurityContext sc, @PathParam("userId") 
                 String userId, UpdateUserRequest request) {
        ExternalUser userMakingRequest = (ExternalUser)sc.getUserPrincipal();
        if(!userMakingRequest.getId().equals(userId)) {
            throw new AuthorizationException("User not authorized to 
               modify this profile");
        }
        boolean sendVerificationToken = 
                 StringUtils.hasLength(request.getEmailAddress()) &&
                !request.getEmailAddress().equals(userMakingRequest.getEmailAddress());
        ExternalUser savedUser = userService.saveUser(userId, request);
        if(sendVerificationToken) {
            verificationTokenService.sendEmailVerificationToken(savedUser.getId());
        }
        return Response.ok().build();
    }
This is an access controlled resource which will be covered in a Part six: security and authorization.

The next post will cover Facebook authentication.






Saturday, January 12, 2013

Writing REST Services in Java: Part 2 User sign up and Login

Previous Post : Part One: Introduction   Next Post : Part Three: Email Verification
Get the Code: https://github.com/iainporter/rest-java

In this post I will walk through the sign up and login services to demonstrate a vertical slice through the application. I will briefly discuss email verification and Social signup but won't delve into that until the next post. Session handling is also deferred until a later post.

User Sign up

To create a User we need to persist some basic information. At a bare minimum we need an email address and a password. Optionally we would like to capture perhaps a first and last name. 
Once a user has signed up we need them to verify their email address. This is important foremost so that we can uniquely identify the user and provide the ability for them to safely reset their password, as well as other security features that depend on a valid email address being provided.

Most services will follow a similar development pattern to this one which is:

1. Define the domain model
2. Write the Repository interface to persist and retrieve the domain objects
3. Write a Service class to map the API object to the entity and CRUD logic to integrate with the Repository, as well as any other services in support of the particular API.
4. Define the API 
5. Write the Resource Controller

The unit tests will test each layer of the application and the Integration Tests will test the full end to end calls through the application.

The User Domain Object

Entities are defined in the com.porterhead.rest.model package. Hibernate annotations are used to manage the joins and Spring Data to manage some of the basic functions common to all entities. All entities have an additional identifier which is a UUID. Some people have a preference to just use a sequential Long to identify an entity. In this application the primary keys are Longs but UUIDs are used in the API calls to persist and retrieve entities.

It comes down to whether you want your urls to look like this:

/user/1

or like this:

/user/38e1e415-acd2-42bb-8a3f-594f13e0d4ea




All entities that we wish to persist are annotated with:

@Entity
@Table(name="table name")

The class is added to the list of known entities in src/main/resources/META-INF/persistence.xml

The beans responsible for persistence are defined in src/main/resources/META-INF/spring/data-context.xml. There are bean profiles for dev, local, staging and production.

The User Repository

The repository tier uses Spring Data which is an excellent framework that takes care of most of the boilerplate headaches with CRUD functionality. The UserRepository class extends the JPARepository interface and has a few custom finder methods defined.

The User Service

The UserService interface defines a method for creating a new User:

public AuthenticatedUserToken createUser(CreateUserRequest request, Role role);

All entities remain within the boundary of the service layer and API objects pass between the Controllers and the services. This allows us to tightly define the contract between clients and the API. All request and responses are defined in the API package. It also prevents potential transaction and hibernate issues by accessing entity objects outside of a transaction. We can also pass API objects to multiple services without worrying about whether that service knows how to persist a particular entity.

It is worth stepping through the implementation of createUser as it will highlight several key features of how service methods are composed.

The method:

    @Transactional
    public AuthenticatedUserToken createUser(CreateUserRequest request, Role role) {
        validate(request);
        User searchedForUser = userRepository.findByEmailAddress(request.getUser().getEmailAddress());
        if (searchedForUser != null) {
            throw new DuplicateUserException();
        }

        User newUser = createNewUser(request, role);
        AuthenticatedUserToken token = new AuthenticatedUserToken(newUser.getUuid().toString(), createAuthorizationToken(newUser).getToken());
        userRepository.save(newUser);
        return token;
    }


First the API request is validated and if it fails an exception is thrown. This is a common pattern in service methods; to fail fast on an error. All Exceptions extend BaseWebApplicationException which defines an error payload for the response and an appropriate Http status code. In this particular case it will be a 400 error and in the case just below a 409 will be returned for the DuplicateUserException.

If no duplicate is found the a User entity is mapped from the request object and persisted.
Note that the password is saved as a one-way hash salted with the UUID of the User.

Finally an AuthenticatedUserToken object is mapped from the created entity and returned from the method.

See com.incept5.rest.service.UserServiceTest for the full suite of tests to run against this service.

The User Resource Controller

Resource classes are responsible for marshalling and unmarshalling client requests and responses and coordinating calls to services. Resource classes do not access entities but instead use objects in the com.incept5.rest.api package to communicate with services.

There are some JAX-RS annotations to map urls to the correct resource:


@Path("/user")
@Component
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})

The method for sign up is:


    @PermitAll
    @POST
    public Response signupUser(CreateUserRequest request) {
        AuthenticatedUserToken token = userService.createUser(request, Role.authenticated);
        verificationTokenService.sendEmailRegistrationToken(token.getUserId());
        URI location = uriInfo.getAbsolutePathBuilder().path(token.getUserId()).build();
        return Response.created(location).entity(token).build();
    }

We specify that it is a POST and the @PermitAll means that the method is not access controlled. In a later post I will walk through customising a sign up for different types of users (customer, merchant, etc). The general sign up just assigns an authenticated role to a new user.

The logic flow is:

1. Call the User Service to handle the create request. If it is successful an API object will be returned with details of the new User.
2. Call the Email Verification Service to send a welcome email along with an embedded link to verify the email address. The details of this will be discussed in the next post. Note that this an asynchronous call and will return as soon as the Verification Service puts the request onto its queue.
3. A location uri for the new resource is created. This takes the form of user/<uuid>. We will see this in the next section when the API is tested with a curl request.
4. The response is gathered and returned. The Http response will be created (201) and the body will contain an AuthenticatedUserToken. Again I will go into more detail about that later.

Testing the API for User sign up

There are in-memory unit tests in the com.porterhead.rest.resource package for testing the Resource classes  but the surest way to test it is by running the code in a servlet container and firing real requests at it.
The integration tests are in the src/test/groovy directory. The tests are written in groovy and executed using the groovy rest client. UserIntegrationTest has tests for both failure and success scenarios.

Testing the API with curl

To test with curl we need to start up the war in a servlet container. The default profile in gradle.properties is dev but if we wanted to test against a real database and a real mail sender we could change that to local or staging and configure the necessary beans. I will discuss how to do that later.
Execute the following command:

gradle tomcatRun

Once the war has finished loading we can execute the following curl request:

curl -v -H "Content-Type: application/json" -X POST -d '{"user":{"firstName":"Foo","lastName":"Bar","emailAddress":"<your email address here>"}, "password":"password"}' http://localhost:8080/java-rest/user

You should see a response like this:

< HTTP/1.1 201 Created
< Server: Apache-Coyote/1.1
< Location: http://localhost:8080/java-rest/user/ff7ffcf0-cfe0-4c1e-9971-3b934612b154
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Sat, 12 Jan 2013 09:43:13 GMT
<  * Connection #0 to host localhost left intact
{"userId":"ff7ffcf0-cfe0-4c1e-9971-3b934612b154","token":"5d1cf32e-e468-4a2c-92b6-9b0c377145f9"}

I'll discuss how to use the response in the next post.

Now that we know sign up works we can test out login.
Try the following curl statement:

curl -v -H "Content-Type: application/json" -X POST -d '{"username":"<your email address here>","password":"password"}' http://localhost:8080/java-rest/user/login


The response:



< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Location: http://localhost:8080/java-rest/user/7ef646ba-5e03-4d59-90a9-822daecf3428
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Sat, 12 Jan 2013 09:52:21 GMT
<
* Connection #0 to host localhost left intact
{"userId":"7ef646ba-5e03-4d59-90a9-822daecf3428","token":"164797a0-623f-427d-a469-b348e7e2bc59"}

That covers user sign up and login. In the next post I will discuss the email verification process.






Friday, January 11, 2013

Writing REST services in Java: Part 1 overview

This is the first in a series of posts walking through setting up a REST application in java. The code accompanying it can be found here https://github.com/iainporter/rest-java

The application contains all the necessary parts to start building new services and deploy them quickly and easily. After checking out the code and making a few configuration changes you can deploy a fully functioning API that includes:

* Signing up a user
* Logging in a user
* Facebook authentication
* Sending email verification
* Verifying email responses
* JSR 303 Validation
* Lost Password
* Role-based authorization
* Request signing
* Session Expiry

I will walk through the various parts in subsequent posts. This will include:


Technologies covered will include:
* Jax-RS (Jersey implementation)
* Spring Data
* Hibernate
* Spring Integration
* Java Mail
* Velocity
* Groovy (for Integration Tests only)
* Deploying to AWS


Building the project 


The project uses gradle to build and deploy. If you don't have gradle installed get it here http://www.gradle.org/

To debug when running in tomcat you can add the following to your bash profile:
export GRADLE_OPTS="-Xmx1024m -XX:MaxPermSize=128M -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8787"


If you have gradle installed then navigate to the root directory and execute

gradle clean build integrationTest

Once it has finished you can inspect the results in build/reports.


Running the Application


From the root directory execute

gradle tomcatRun

When the servlet container has loaded the war run the following curl request:


curl -v -H "Content-Type: text/html" -X GET  http://localhost:8080/java-rest/healthcheck


You should see the following response:


< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Date: Thu, 10 Jan 2013 19:21:02 GMT
< Running version 1.0.0

The application is now successfully running.


The Project Structure

At the root there are two files that control how the project is built:

build.gradle
gradle.properties


Build Tasks


gradle clean - cleans out the build directories
gradle build - compiles the source, runs the unit tests, writes test and coverage reports, builds the WAR file
gradle integrationTest - runs the groovy integration tests and appends to the test report
gradle tomcatRun - starts the tomcat container and loads the WAR file


Spring Profiles

The project makes use of Spring Profiles. When running from gradle commands the active profile is loaded from the gradle.properties file.

There are four profiles:

dev - runs in-memory database, Mock Mail Sender
local - runs against local instance of mySQL DB, Mock Mail Sender
staging - runs against a configured DB instance and configured staging Mail Sender
production - runs against a configured DB instance and configured production Mail Sender


Unit Tests and Code Coverage

Unit tests are in the src/test/java directory and are ran against the DEV profile. 
Integration tests are in the src/test/groovy directory. These tests are ran in a Jetty servlet container against the DEV profile. You can change the profile to local if you want to capture the results in your local DB store. The main principle of the integration tests is that they exercise the API in the guise of a client. This means that all requests and responses are json structures and not built against any server side API components.
Code coverage uses the emma plugin



The Architecture






A typical message flow is:

1. The client makes a RESTful request (either PUT, POST, GET or DELETE) using Json payloads.
2. The servlet filter routes all requests through the Authorization filter.
3. If there is a valid Authorization header the authorization service performs validation and identifies the User making the request
4. Control is passed to the Resource Controller that handles resources of that type. 
5. A Roles-based filter checks the user has access control for that resource request.
6. The Json payload (if present) is marshalled to an API object
7. The Resource Controller communicates with one or more Services by passing back and forth API objects
8. The Service tier is responsible for managing the lifecycle of entities and integration with any external services as well as transformation mappings between entities and API objects
9. The Repository tier manages persistence and retrieval of entities
10. Responses are returned by the Resource Controllers, unmarshalled to Json and returned to the client


In the next post I'll dig into the details of sign up and login.