Friday, July 19, 2013

Use Spring JavaMailSender and Freemarker to send Newsletter from your JSF2 applications

Newsletters are a very powerful way to keep in touch with your web site users. They also are widely used as a mean of marketing. So how to generate and send a Newsletter in your JSF2 application ?

1) Use a template engine

As stated in Wikipedia, a template engine is "a software that is designed to process web templates and content information to produce output web documents".
So the idea is very simple, like when dealing with Facelets pages, we define a template page for our Newsletter, and then use the template engine to generate a new text based on merging this template and data we pass to it.
There are so many template engines in the open source market. Between them there is Freemarker, Velocity, StringTemplate, Thymeleaf and so many others. Personally I worked with Velocity and Freemarker. Both are very flexible and very powerful. 
If you want to use Velocity with your Newsletters you can find a little example for Spring integration here. In this article we will be using Freemarker.

2) Pick a template for Newsletter

First thing to do (just as when developing a web page) is to design our Newsletter. You can ask your designer to create a static pure HTML Newsletter template. For me, I just chose this free template. And here is a screenshot of it:

It's quite simple. It contains a list of head titles (under "In this issue"). It contains also a list of latest articles: every article will contain a title, a description and eventually an image (the image can be null). The newsletter will also contain a link to unsubscribe from our mailing list. 

3) Add Maven dependencies

You need to add Freemarker, JavaMail (required by Spring mail) and if you didn't already include it, Spring Context support. So in your POM file, make sure to include these dependencies:



  org.springframework
  spring-context-support
  ${org.springframework.version}



 javax.mail
 mail
 1.4.7

        

 org.freemarker
 freemarker
 2.3.14

4) Data model

Now we need to prepare our data model (if you didn't already) for the newsletter. As I said, we will display a list header titles (let's say this will present flash news), and a list of latest articles and an unsubscribe link.
This is our Article class:

package com.raissi.domain.newsletter;

import java.io.Serializable;

public class Article implements Serializable{
	private static final long serialVersionUID = 2999207145055407788L;

	private String title;
	private String image;
	private String description;
	
	public Article() {
		super();
	}
	public Article(String title, String image, String description) {
		super();
		this.title = title;
		this.image = image;
		this.description = description;
	}
	
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getImage() {
		return image;
	}
	public void setImage(String image) {
		this.image = image;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}		
}
For simplicity matter, I will use just a map of (title,url) pairs to display header titles. As for the unsubscribe link, it will point to unsbscribe-newsletter?token=encryptedUserEmail.

5) Implementation

5-a) Spring config

Spring provides a JavaMailSender utility that helps with handling mails, we will use it, 

	
	
	
	
		
			${mail.smtp.auth}
			${mail.smtp.port}
			${mail.host}
			true
		
	

Now add the Freemarker Configuration bean factory:




	
	
	

I think comments well explain each element in the above config.
Now let's create a service class that will be responsible for processing the template, generating the mail message and sending it via defined mailSender bean, in Spring add:

	
	

5-b) Service classes

And here is the MailService class:
package com.raissi.service.mail;

import java.util.Map;

import javax.mail.internet.MimeMessage;

import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import freemarker.template.Configuration;

public class MailService {

	private JavaMailSender javaMailSender;
	private Configuration freemarkerConfiguration;
	
	public void sendMail(final String from, final String to, final String subject, final Map model, final String template){
		MimeMessagePreparator preparator = new MimeMessagePreparator() {
	         public void prepare(MimeMessage mimeMessage) throws Exception {
	            MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
	            message.setFrom(from, "Raissi JSF2 sample");
       		    message.setTo(to);
       		    message.setSubject(subject);
       		    //template sample: "com/raissi/freemarker/confirm-register.ftl"
                String text = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConfiguration.getTemplate(template,"UTF-8"), model);
	            message.setText(text, true);
	         }
	      };
		javaMailSender.send(preparator);
	}

	public void setJavaMailSender(JavaMailSender javaMailSender) {
		this.javaMailSender = javaMailSender;
	}

	public void setFreemarkerConfiguration(Configuration freemarkerConfiguration) {
		this.freemarkerConfiguration = freemarkerConfiguration;
	}	
}
The only tricky part of this class is the FreeMarkerTemplateUtils.processTemplateIntoString call. This method "Process the specified FreeMarker template with the given model and write the result to the given Writer." As for the model parameter, it's typically a Map that contains model names as keys and model objects as values.
This service class will be used by every class desiring to send an email with Freemarker as Template Engine in our application.
Now let's define a NewsLetterService class that will fetch data to be filled into the newsletter and then call mailService.sendMail:

package com.raissi.service.newsletter.impl;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.raissi.domain.User;
import com.raissi.domain.newsletter.Article;
import com.raissi.service.UserService;
import com.raissi.service.mail.MailService;
import com.raissi.service.newsletter.NewsLetterService;

@Service("newsLetterService")
@Transactional
public class NewsLetterServiceImpl implements NewsLetterService{
	private static final long serialVersionUID = -6291547874161783407L;
	
	@Inject	
	private @Named("mailService")MailService mailService;
	@Inject
	private UserService userService;
	
	public void sendNewsLetter(User user){
		//Generate the Unsubscribe link, it will contain the user's email encrypted
		try {
			/*
			 * Will generate a complete url to the specified pageName and containing the tokenToBeEncrypted 
			 * as encrypted param, ex: http://mysite.com/confirm-registration?token=userNameEncrypted 
			 */
			String unsubscribeUrl = userService.generateUserToken("unsbscribe-newsletter", user.getEmail());
			//Get the site base url from the above url, and use it for images urls
			//It will be in the form: http://mysite.com/resources/freemarker
			String baseUrl = unsubscribeUrl.substring(0,unsubscribeUrl.indexOf("/unsbscribe")+1)+"resources/freemarker";
			List
latestArticles = getLatestArticles(); Map headerTitles = getHottestNews(); String newsSourceUrl = "http://www.richarddawkins.net/"; String newsSourceName = "Richard Dawkins Foundation for Reason and Science"; Map model = new HashMap(); model.put("unsubscribeUrl", unsubscribeUrl); model.put("latestArticles", latestArticles); model.put("headerTitles", headerTitles); model.put("newsSourceUrl", newsSourceUrl); model.put("newsSourceName", newsSourceName); model.put("baseUrl", baseUrl); mailService.sendMail("raissi.java@gmail.com", user.getEmail(), "Our Newsletter", model, "com/raissi/freemarker/newsletter.ftl"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public Map getHottestNews(){ Map news = new HashMap(); //Just for testing purpose, we will generate a static list of news news.put("Richard Dawkins to headline unique Bristol event, Sat. 24th August","http://www.richarddawkins.net/news_articles/2013/7/19/richard-dawkins-to-headline-unique-bristol-event-sat-24th-august-2013"); news.put("Parliament 'must pardon codebreaker Turing'","http://www.richarddawkins.net/news_articles/2013/7/19/parliament-must-pardon-codebreaker-turing"); news.put("Curiosity team: Massive collision may have killed Red Planet","http://www.richarddawkins.net/news_articles/2013/7/19/curiosity-team-massive-collision-may-have-killed-red-planet"); news.put("Tyrannosaurus rex hunted for live prey","http://www.richarddawkins.net/news_articles/2013/7/18/tyrannosaurus-rex-hunted-for-live-prey"); return news; } public List
getLatestArticles(){ List
latestArticles = new ArrayList
(); //Just for testing purpose, we will generate a static list of Articles //Noam Chomsky String chomskyDesc = "Avram Noam Chomsky (/ˈnoʊm ˈtʃɒmski/; born December 7, 1928) is an American linguist," + " philosopher, cognitive scientist, logician, political critic, and activist. " + "He is an Institute Professor and Professor (Emeritus) in the Department of Linguistics & Philosophy at MIT, " + "where he has worked for over 50 years. " + "In addition to his work in linguistics, he has written on war, politics, and mass media, " + "and is the author of over 100 books.[13] Between 1980 and 1992, " + "Chomsky was cited within the field of Arts and Humanities more often than any other living scholar, " + "and eighth overall within the Arts and Humanities Citation Index during the same period." + " He has been described as a prominent cultural figure, and was voted the \"world's top public intellectual\" " + "in a 2005 poll.[18]"; String chomskyImg = "http://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Chomsky.jpg/200px-Chomsky.jpg"; Article noamChomsky = new Article("Noam Chomsky", chomskyImg, chomskyDesc); latestArticles.add(noamChomsky); //Richard Dawkins String dawkinsImg = "http://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Richard_Dawkins_Cooper_Union_Shankbone.jpg/250px-Richard_Dawkins_Cooper_Union_Shankbone.jpg"; String dawkinsDesc = "Clinton Richard Dawkins, FRS, FRSL (born 26 March 1941) is an English ethologist," + " evolutionary biologist and author. He is an emeritus fellow of New College, Oxford," + " and was the University of Oxford's Professor for Public Understanding of Science from 1995 until 2008."; Article richardDawkins = new Article("Richard Dawkins", dawkinsImg, dawkinsDesc); latestArticles.add(richardDawkins); //Stephen Hawking String hawkingDesc = "Stephen William Hawking CH, CBE, FRS, FRSA (Listeni/ˈstiːvɛn hoʊkɪŋ/; stee-ven hoh-king; born 8 January 1942) " + "is an English theoretical physicist, cosmologist, author and Director of Research at the Centre for Theoretical Cosmology" + " within the University of Cambridge. Among his significant scientific works have been a collaboration with " + "Roger Penrose on gravitational singularities theorems in the framework of general relativity, " + "and the theoretical prediction that black holes emit radiation, often called Hawking radiation." + " Hawking was the first to set forth a cosmology explained by a union of the general theory of " + "relativity and quantum mechanics. He is a vocal supporter of the many-worlds interpretation of quantum mechanics."; Article stephenHawking = new Article("Stephen Hawking", null, hawkingDesc); latestArticles.add(stephenHawking); //Paul Nizan String nizanImg = "http://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Nizanpaul.jpg/220px-Nizanpaul.jpg"; String nizanDesc = "Paul-Yves Nizan (French: [nizɑ̃]; 7 February 1905 – 23 May 1940) was a French philosopher and writer. " + "He was born in Tours, Indre-et-Loire and studied in Paris where he befriended fellow student Jean-Paul Sartre at the Lycée Henri IV." + " He became a member of the French Communist Party, and much of his writing reflects his political beliefs, " + "although he resigned from the party upon hearing of the Molotov-Ribbentrop Pact in 1939. " + "He died in the Battle of Dunkirk, fighting against the German army in World War II."; Article paulNizan = new Article("Paul Nizan", nizanImg, nizanDesc); latestArticles.add(paulNizan); return latestArticles; } }

The code of this class is very simple, there is only one thing that may be not clear. It's the call to userService.generateUserToken. In fact this method, is just a simple utility method to generate a url containing the specified token param encrypted and pointing to the passed page name param, here is its implementation:
public String generateUserToken(String pageName, String tokenToBeEncrypted) throws UnsupportedEncodingException{
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String domain = "http://"+request.getServerName()+":"+request.getServerPort();
		String context = servletContext.getContextPath();
		//As in the getContextPath() docs, The path starts with a "/" character but does not end with a "/" character 
		context = domain+context;
		String encryptedToken = URLEncoder.encode(textEncryptor.encrypt(tokenToBeEncrypted),"UTF-8");
		return context+"/"+pageName+"?token="+encryptedToken;
}
Now everything is ready, but only the template page.

5-c) The Freemarker Template

To create the template, just copy the code of static HTML template that you chose (or your designer) and modify it by adding dynamic parts.
Let's start by the header titles. We said they are links to some news. In our Java data model, we passed them within a Map<String, String>: the title of the news is the key and the url is the value. The map is then put into the model param under the headerTitles key. To display this map in Freemarker, we use this syntax:

<#list headerTitles?keys as title>
    ${title}
</#list>

As for the latest articles list, we passed them as a List<Article> object under the key with value: latestArticles, and here is the Freemarker code to display that list:
<#list latestArticles as article>
${article.title}
<#if article.image??>																															</#if>
${article.description}
</#list>
Of course, here I omitted the CSS code and other design related HTML code.
As for the unsubscribe link, you should be able to guess its value:

Unsubscribe
As we passed the url to unsubscribe under the unsubscribeUrl within model param.
This is how my Newsletter seems as received in my Yahoo mail account (a part of, that my screen can display):

By now you should be able to send any kind of newsletter to your users.

6) Final (and very important) remarks

6-a) Inline styles

If you are using CSS styles defined in the head section of your template, then most of email clients will ignore it. See this link. So what will you do ? 
The answer is to use inline style, for example: 
instead of defining a style class that won't be recognized.
Now you be saying, but f**k how will I transform all those CSS classes into inline style? Well, the answer is with this awesome site.

6-b) Asynchronous execution

If you will use the above java MailService class as it's, and if you provide the user a button or a link to send him newsletter (or any other king of emails) when clicked, then the UI will be blocked until email is sent. And since this may take some long time (depending on your Email server and other Internet params), the process of sending emails should run asynchronously. You may think about using a Java Thread, which is completely legitimate.
The good news, is that Spring (with its great magic) offers the possibility of running methods asynchronously by simply adding an annotation: @Async. So in your MailService class annotate your sendMail with Async.
Note you must add the following directive (XML element) to your application context file, so that Spring will recognize the Async annotation:


    
    


And by now everything should be just perfect.
It will be great to see your comments

Thursday, July 18, 2013

JSF 2, Spring, Spring Security, Hibernate/JPA, Jasypt, application sample available at Github

If you have followed my previous articles series about JSF 2 and different frameworks integration, then you can find the complete application source code on Github here.
Please feel free to post your comments, suggestions and ameliorations

Protect you users passwords in with Jasypt

As recommended by OWASP, when storing users credentials, you always should encrypt user's password in a way that protects it from being stolen. In fact, if you are saving them in clear, and once your DB has been stolen, or accessed by even your DBA, this will make all passwords compromised. Now what about a user that used the same password for your application and his bank online account?
This been said, you should encrypt these passwords. And to do it, you have one of two possibilities:
1) Encrypt the password and save it in DB. For every attempt to login, retrieve the encrypted password, decrypt it and compare it to given password.
2) When user is registering, generate a hash code for his password and save it in DB. For every attempt to login, compare the stored hash with the generated hash of given password when login happens.
Both methods are robust if using robust algorithms. But I prefer second one. In fact, using the hash codes, makes the user the only person who can know the real password value. The first one, makes it possible for application developer to guess it.
In this article we will use Jasypt library to implement both methods. Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works.

1) Transparent password encryption with Hibernate

To implement the first approach to secure passwords, Jasypt offers a very simple and transparent enryption method. To do it, just declare the following bean in your spring context:



     
          hibernateStringEncryptor
     
     
         simplepassword
     

This will create a HibernatePBEStringEncryptor object and register it with the "hibernateStringEncryptor" name. You should use a strong password to be used when encrypting your data.

Now, we only need to add Jasypt annotations to properties we want to be encrypted transparently, here is the User entity class:
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.Type;
import org.jasypt.hibernate4.type.EncryptedStringType;
@Entity
@Table(name="user_table")
@TypeDef(
        name="encryptedString", 
        typeClass=EncryptedStringType.class, 
        parameters={@Parameter(name="encryptorRegisteredName",
                               value="hibernateStringEncryptor")}
)
public class User implements Serializable{
   //properties, here, especially the password property that we want to be encrypted:

   @Type(type="encryptedString")
   private String password;

   //Getters and Setters etc...
}
And that's all you need to do, now you can save your user objects and check the password field in DB, it will be encrypted.
Now when you wish to login a user, just check password equality as follows:
@Transactional(readOnly=true)
public User loginUser(String login, String password) {
        User user = userDao.findUserByLoginOrEmail(login);
 if(user != null ){
  if(password.equals(user.getPassword() )){
   return user;
  }
 }
 return null;
}
As you can see, we are not performing any encryption operation on data. Everything is transparent.
Please notice: never and ever use the password field on a where sql(or hql or jpql) query once it's annotated with @Type(type="encryptedString"), since it will be stored as an encrypted value, and you have no mean to compare an encrypted value against it.

2) Digest (hash code) generation for passwords

Now let's see the secodn (and my preferred method) for storing passwords. First thing to do, is to create a StringDigester bean in Spring: 



Although you can just instantiate this object whenever needed, I just wanted it to be a singleton object in the whole application. Now inject it in your service class and use it to digest passwords when saving users:
@Inject
private @Named("stringDigester")StandardStringDigester digester;
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void saveUser(User user){
        //Digest password and save it
 user.setPassword(digester.digest(user.getPassword()));
 userDao.save(user);
}

//Login method:
@Transactional(readOnly=true)
public User loginUser(String login, String password) {
 User user = userDao.findUserByLoginOrEmail(login);
 if(user != null ){
           //Call StandardStringDigester.matches to compare stored digest and provided password
  if(digester.matches(password, user.getPassword())){
   return user;
  }
 }
 return null;
}
And that's it, now you are sure that your passwords are stored in a safe way.

Wednesday, July 10, 2013

JSF 2, display PDF files stored at Amazon S3 for cloud storage

Lately I have been working on a personal project using JSF2. In that project I had to display PDF files to users on demand. I wanted to deploy the project in the cloud and I chose CloudBees. The only problem I encountered with CloudBees is that you cannot upload files via your application to their servers.
The solution was to store my files in an external storage provider. I chose Amazon Simple Storage Service (S3).
Now here is the challenge: I have my files stored at Amazon servers, and I need to remotely access these files and display them back to users via Google Docs Viewer. You may say that I could generate direct URL to these files (as discussed here) and then simply display them. But, what if you don't want them to be publicly accessible, or if you want to make them accessible under some conditions ?
In this article we will see how to do this. But first let's begin with uploading files to Amazon S3 via our JSF2 application.

1) The JetS3t Toolkit

The JetS3t is an open source application suite for Amazon S3, Amazon CloudFront content delivery network and Google storage for developers. It provides a very simple  API for interacting with these storage services. Here is POM dependencies for JetS3t:




 net.java.dev.jets3t
 jets3t
 0.9.0

2) Uploading files in JSF2

To upload files, we will use Primefaces uploader. To use it, you should define PrimeFaces FileUpload Filter in your web.xml descriptor:



 PrimeFaces FileUpload Filter
 org.primefaces.webapp.filter.FileUploadFilter


 PrimeFaces FileUpload Filter
 Faces Servlet
 
 FORWARD

Please notice that we set dispatcher to FORWARD. This because we are using Prettyfaces (it's filter dispatcher is also set to FORWARD). Without doing this, you may encounter some problems.
You also must add dependencies of two additional APIs: commons-io and commons-fileupload. It's not mentioned in Primefaces docs, but without doing this, you will get many ClassNotFoundExceptions related to theses libraries:



 commons-fileupload
 commons-fileupload
 1.3


 commons-io
 commons-io
 2.4

Now everything is set alright. Let's begin with implementation. The JSF upload part is very simple. You simply define a managed bean containing an UploadedFile property and two methods:
package com.raissi.managedbeans;
import java.io.IOException;
import java.io.Serializable;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.raissi.domain.Resume;
import com.raissi.service.ResumeService;

@Component
@Scope("view")
public class HomeManagedBean implements Serializable{
 private static final long serialVersionUID = 5426154702541976181L;
 @Inject
 private ResumeService resumeService;
        private Resume resume = new Resume();
 private UploadedFile file;

 public UploadedFile getFile() {
          return file;
 }

  public void setFile(UploadedFile file) {
          this.file = file;
 }
    
 public void fileUploadListener(FileUploadEvent event){
       file = event.getFile();
 }
        public void upload() {
          if(file != null) {
      try {
       resume.setDocumentName(file.getFileName());
    resumeService.persistCvContent(file.getInputstream(), resume);
    loggedInUser.getUser().setResume(resume);
    FacesMessage msg = new FacesMessage("Succesful", file.getFileName() + " is uploaded.");
             FacesContext.getCurrentInstance().addMessage(null, msg);
  } catch (IOException e) {
    FacesMessage msg = new FacesMessage("File ", file.getFileName() + " couldn't be uploaded. Please contact admins");
             FacesContext.getCurrentInstance().addMessage(null, msg);
    e.printStackTrace();
  }
          }
        }
}
And here is our xhtml code:

      
      
     
      
       
       
       
       
       
        
                
                
                
                
      
     
    
     
The Resume class referenced in the managed bean, is just a domain class that we defined in last article. It will contain data related to user's resume and will be persisted in DB. The key class here is the ResumeService bean which is responsible for Resume persistence in both DB via ResumeDao and in remote Amazon S3 store. Before we go through document persistence in Amazon S3, please make sure you got your your Amazon S3 credentials: AWSAccessKeyId (access key ID) and AWSSecretKey (Secret Key) since we will use them to store/retrieve data from S3.

3) Persisting files to Amazon S3 

Now we go to examine the ResumeService class:

package com.raissi.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.io.IOUtils;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.ServiceException;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import com.raissi.dao.ResumeDao;
import com.raissi.domain.Resume;
import com.raissi.service.ResumeService;

@Named("resumeService")
@Transactional
public class ResumeServiceImpl implements ResumeService, Serializable{
 private static final long serialVersionUID = 1L;
 
 @Inject
 private ResumeDao resumeDao;
 @Value("${s3.accessKeyId}")
 private String amazonAccessKeyId;
 
 @Value("${s3.secretKey}")
 private String amazonSecretKey;
 
 @Value("${s3.bucketName}")
 private String bucketName;
 
 private S3Service s3Service;
 // To store data in S3 you must first create a bucket, a container for objects.
 private S3Bucket bucket;
 @PostConstruct
 public void init(){
  try {
   //amazon S3 storage credentials:
   AWSCredentials awsCredentials = 
       new AWSCredentials(amazonAccessKeyId, amazonSecretKey);
   //To communicate with S3, create a class that implements an S3Service. 
   //We will use the REST/HTTP implementation based on HttpClient, 
   //as this is the most robust implementation provided with JetS3t.
   s3Service = new RestS3Service(awsCredentials);
   
   bucket = s3Service.getBucket(bucketName);
   if(bucket == null){
    bucket = s3Service.createBucket(bucketName);
   }
  } catch (S3ServiceException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

        @Override
 public void persistCvContent(InputStream content, Resume resume) {
  long currentTime = System.currentTimeMillis();
  String extension = resume.getDocumentName().substring(resume.getDocumentName().lastIndexOf("."));
  String fileName = currentTime+extension;
  
  try {
   byte[] contentArray = IOUtils.toByteArray(content);
   S3Object cvS3Object = new S3Object(fileName, contentArray);
   cvS3Object.setContentLength(contentArray.length);
   cvS3Object.setContentType("application/pdf");
   s3Service.putObject(bucket, cvS3Object);
   resume.setContentUrl(bucketName+"/"+fileName);
  } catch (S3ServiceException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}
A bucket in Amazon S3 is a file container in which every uploaded file will be stored. A bucket name must be unique through all S3 users. Buckets cannot be nested. And, each bucket can contain an unlimited number of files. I decided bucket name to be configurable with accessKeyId and secretKey. That's why I am injecting their values in my ResumeService, so application admin can chose whatever he wants. (Remember the property-placeholder defined in Spring application context in last article, well these String values should be defined in the file referenced by the properties holder).
Also notice that we are saving the distant file name and the bucket name in a persistent entity "Resume". In this way, we are able to use different bucket names in the future.

4) Displaying PDF files in JSF2

To display PDF files, we can simply use 


From Primefaces. But this is for static and public files (accessible by simple URLs). For dynamic files which need some server logic before rendering we can use a custom servlet with the above primefaces component.
Use case: Assume we have a datatable displaying a list of users (User object from last article). For each row (User) we will have a button to view CV. When clicked, the button opens a popup dialog displaying the PDF file. So here is the XHTML code:



     
                 Registered users
                 
               
           
   
           
               
            
           
           
            
               
           
                  
               
              
                        
               
        
       
              
             
As you can see, the command button used to display the dialog has an action listener to call a server side method: generateUserCV(User user); the method code is:
public void generateUserCV(User user){
  setSelectedUser(user);
  if(user != null){
   InputStream file = resumeService.getCvByUser(user.getUserId());
   if(file != null){
    try {
     byte[] bytes = IOUtils.toByteArray(file);
     Map session = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
     //We are using userId when storing cv content to be possible to display multiple files 
     session.put(ResumeService.ATTR_RESUME+user.getUserId(), bytes);
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    
   }
  }
}
As for the generateUserCV method, it calls the resumeService to get user's CV file as java.io.InputStream. Then, we use org.apache.commons.io.IOUtils#toByteArray(InputStream input) to convert file content a byte array. After that we save the array in the session map under a constant String (ResumeService.ATTR_RESUME) of our choice concatenated with the user id. This will be used by the mentioned custom servlet later. Now here is the code of resumeService.getCvByUser:
public InputStream getCvByUser(Long userId){
  Resume resume = resumeDao.getResumeByUser(userId);
  String fullS3Name = resume.getContentUrl();
                //Remember, we set the bucket name and file name in the contentUrl property of Resume
  String bucketNameForResume = fullS3Name.substring(0, fullS3Name.indexOf("/"));
  String fileName = fullS3Name.substring(fullS3Name.indexOf("/")+1);
  try {

   S3Object cvS3Object = s3Service.getObject(bucketNameForResume, fileName);
   if(cvS3Object != null){
    InputStream stream = cvS3Object.getDataInputStream();    
    return stream;
   }
  } catch (S3ServiceException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (ServiceException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  return null;
 }
In the dialog to be shown, you may have noticed that we are using p:media with a stream value: /file/cv?id=#{adminHomeManagedBean.selectedUser.userId}. Well, here we are referring to a GET call to a servlet with a param named "id". And here is the servlet implementation:
package com.raissi.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.raissi.service.ResumeService;

@WebServlet("/file/cv")
public class ResumeServlet  extends HttpServlet {
 private static final long serialVersionUID = -221600603615879137L;

 @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  String userId = request.getParameter("id");
  if(userId != null && !userId.equals("")){
         byte[] content = (byte[]) request.getSession().getAttribute(ResumeService.ATTR_RESUME+userId);
            if(content != null){
          response.setContentType("application/pdf");
          response.setContentLength(content.length);
          response.getOutputStream().write(content);
            }
  }
    }

}
The code is very obvious. At first, we fetch the user id (user of whom we are displaying CV) from request parameters. After that, we access the HTTPSession to retrieve the stored content and we set it into response output. Finally, we need to clean our session when dialog is closed. Otherwise, session will be encumbered with content. That's why I added a listener to be called on dialog close event: . And here is the listener code:
public void removeUserCVFromSession(CloseEvent event){
  if(selectedUser != null){
   Map session = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
   session.remove(ResumeService.ATTR_RESUME+selectedUser.getUserId());
  }
 }
And that's all you need.

JSF2, Spring and Hibernate/JPA integration

In a previous article we saw how to integrate Spring with JSF2  and how to define custom JSF2 scopes in Spring. In this part, we will add support of JPA (through Hibernate) to our application.
As you should know Hibernate is an open source Java persistence framework that implements JPA.  If you are not familiar with Hibernate and JPA please refer to documentation for more informations.
In this article , we will create a simple data model consisting of two tables: CV and USER_TABLE. For simplicity user_table will refer to cv table via a foreign key.
Before we start, please add following dependencies to your POM file:



 org.hibernate
 hibernate-core
 4.3.0.Beta2


 org.hibernate
 hibernate-entitymanager
 4.3.0.Beta2

 

 antlr
 antlr
 20030911

1) Tables creation

Notice that I am using MySQL here.
Table CV
CREATE TABLE `cv` (
 `cv_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
 `objective` TEXT NULL,
 `content_url` VARCHAR(255) NULL DEFAULT NULL,
 `title` VARCHAR(255) NOT NULL,
 `document_name` VARCHAR(255) NOT NULL,
 PRIMARY KEY (`cv_id`)
)
ENGINE=InnoDB;
Table USER_TABLE
CREATE TABLE `user_table` (
 `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
 `firstname` VARCHAR(50) NULL DEFAULT NULL,
 `lastname` VARCHAR(50) NULL DEFAULT NULL,
 `email` VARCHAR(255) NULL DEFAULT NULL,
 `login` VARCHAR(30) NOT NULL,
 `password` VARCHAR(30) NOT NULL,
 `address` VARCHAR(100) NULL DEFAULT NULL,
 `role` VARCHAR(30) NULL DEFAULT 'USER',
 `cv_id` BIGINT(20) NULL DEFAULT NULL,
 PRIMARY KEY (`user_id`),
 INDEX `FK_20732bf2152840f1b10160c7a1f` (`cv_id`),
 CONSTRAINT `FK_20732bf2152840f1b10160c7a1f` FOREIGN KEY (`cv_id`) REFERENCES `cv` (`cv_id`)
)
ENGINE=InnoDB;

2) Domain classes

After creating tables, we should create corresponding classes to be mapped via JPA:


package com.raissi.domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="cv")
public class Resume implements Serializable{
 private static final long serialVersionUID = -6450539497238528693L;
 
 @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cv_id")
 private Long id;
 @Column(name = "title")
 private String title;
 @Column(name = "objective", nullable = false)
 private String description;
 @Column(name = "content_url", nullable = false)
 private String contentUrl;
 @Column(name = "document_name", nullable = false)
 private String documentName;
 
 public Resume() {
  super();
 }
        //Getters and setters...
}
package com.raissi.domain;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.raissi.domain.Resume;

@Entity
@Table(name="user_table")
public class User implements Serializable{

    private static final long serialVersionUID = 3571343460175211199L;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //Generator user_seq
    @Column(name = "user_id")
    private Long userId;
    @Column(name = "login", nullable = false)
    private String login;
    @Column(name = "password", nullable = false)
    private String password;
    @Column(name = "firstname", nullable = false)
    private String firstName;
    @Column(name = "lastname", nullable = false)
    private String lastName;
    @Column(name = "address")
    private String address;
    @Column(name = "email", nullable = false)
    private String email;
    @Column(name = "role", nullable = false)
    private String role = "USER";
 
    @ManyToOne( cascade = {CascadeType.MERGE})
    @JoinColumn(name="cv_id")
    private Resume resume;
 
    public User() {
 super();
    }
 
    //Getters and setters here...
}
Now that we have our our tables and corresponding tables in place, let's create a Data Access Objects layer.

3) DAO layer

In this layer, I will use for each persistent object, a DAO interface and an implementation for the it. This is the recommended way, especially when working with IoC design pattern. 
package com.raissi.dao;

public interface BaseDao {
    public void save(Object o);
    public void update(Object o);
    public void delete(Object o);
}
package com.raissi.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
public class BaseDaoImpl implements BaseDao{
 
    protected EntityManager entityManager;

    @Override
    public void save(Object o) {
 entityManager.persist(o);
    }

    @Override
    public void update(Object o) {
        entityManager.merge(o);
    }

    @Override
    public void delete(Object o) {
 entityManager.remove(o);
    }
 
    @PersistenceContext
    void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}
Here we defined a base CRUD operations class. It will be inherited by all other DAO classes.
package com.raissi.dao;

import com.raissi.domain.Resume;

public interface ResumeDao extends BaseDao{
 public Resume getResumeByUser(Long userId);
}
package com.raissi.dao;

import javax.inject.Named;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import com.raissi.domain.Resume;

@Named("resumeDao")
public class ResumeDaoImpl  extends BaseDaoImpl implements ResumeDao{

 @Override
 public Resume getResumeByUser(Long userId) {
  try {
  Query query = entityManager
  .createQuery("from Resume res where res.id = " +
    "(select user.resume.id from User user where user.userId = :userId)").setParameter("userId", userId);
  return (Resume) query.getSingleResult();
  }catch (NoResultException ex) {
   return null;
  }
 }
}
package com.raissi.dao;

import java.util.List;
import com.raissi.domain.User;

public interface UserDao extends BaseDao{
 public User findUserByLoginOrEmail(String loginOrEmail);
}
package com.raissi.dao;

import java.util.List;

import javax.inject.Named;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import com.raissi.domain.User;

@Named("userDao")
public class UserDaoImpl extends BaseDaoImpl implements UserDao{
@Override
 public User findUserByLoginOrEmail(String loginOrEmail) {
  try {
   Query query = entityManager
     .createQuery("from User user where user.login=:login or user.email=:email")
     .setParameter("login", loginOrEmail).setParameter("email", loginOrEmail);
   return (User) query.getSingleResult();
  } catch (NoResultException ex) {
   return null;
  }
 }
}
Now that we have our DAO layer prepared (notice the entityManager injected in the BaseDaoImpl class), we need to inform Hibernate where to find our tables.

3) JPA configuration with Spring

If you followed my last article about Spring Security, you would have seen that we configured a datasource via Spring:







 
 
 
  
   
   
   
  
        

The last defined bean: entityManagerFactory is a factory that will build and return the entityManager we injected in our DAO classes via @PersistenceContext annotation.
Now you may notice that we are referring to a "cvtheque" value as a "persistenceUnitName" in the entityManagerFactory bean. In JPA, you must have a a file named "persistence.xml" under a folder named META-INF in you classpath (I created the folder META-INF under src/main/resources). This file must define the persistence unit:


    
      
         
         
         
      
   

In this persistence config, you may pass Hibernate parameters like show_sql. By now you should be able to use your DAO layer and communicate with you DB tables.

4) Transactions

Now, if you want to save a new User object into your database using this code in a DAO class, let's say a generic class responsible for basic CRUD operations of all objects:

public void save(Object o) {
     entityManager.persist(o);
}
And in service class, UserServiceImpl you call this method:
public void saveUser(User user){
 userDao.save(user);
}
Then when calling the method UserService#saveUser from a managed bean, you may notice that everything works fine, except one thing, data is not persisted into DB (user not saved). Well this is pretty normal. We don't have any transaction opened to commit data into DB. In fact, "No communication with the database can occur outside of a database transaction" (read more here). So what to do ?
Well, you need to open transaction before every data change aimed to be done on DB, do logic and then commit transaction.
Without Spring: if you are not using Spring (especially, Spring Transactions) or another Transaction management framework, then you have to manage your transactions manually, like this in your previously mentioned BaseDAO class:

public void save(Object o) {
 EntityTransaction tx = null;
 try {
     tx = entityManager.getTransaction();
     tx.begin();
     entityManager.persist(o);
     tx.commit();
 }
 catch (RuntimeException e) {
     if ( tx != null && tx.isActive() ) tx.rollback();
     throw e; // or display error message
 }
 finally {
  entityManager.close();
 }
}
As you can see this is a very much code to write just to call the entityManager.persist(o); instruction. Hopefully, Spring come with a framework to manage transactions for us using AOP annotations.
With Spring Transactions: to make a method transactional (i.e. be executed in a transaction), all we need is annotate that method with @Transactional.
Usually, you will want to make your service layer transactional. In fact, a transaction must go inline with the ACID properties (Atomic, Consistent, Isolated, Durable). And by this, if a service layer method,only requires a one call to the DB, than the transaction will contain only that DB access. However, if a single service method needs to execute two or more related operations, and among them there is a DB save operation. If you made only DB access method as transactional, then, when an error occurs while doing the service logic (or during the DB transaction) then only some logic will get executed. A good example for this situation is this service method:

public void bookArticle(User user, Article article, int quantity){
 articleDao.retrieveFromStock(article, quantity); //decrease the number of articles available in DB
 doPayment(user, quantity, article);//Make the payment
}
Now suppose that for a reason or another, the doPayment method throws an exception. If you didn't think about that, then you will get your DB messed up every time there is a payment problem. And you will find yourself obliged to handle these error by re-adding back the already decreased number of articles into DB.
And for this reason, you should make every service logic that is related by the ACID properties in the same transaction, like the above bookArticle method.
How to do it in Spring words
First thing to do is to add the transaction Spring framework, here is maven dependencies:


  org.springframework
  spring-tx
  ${org.springframework.version}

After that, you need to add Spring transactions configs to your applicationContext.xml file, here what needs to be added (I chose to write the beans root element here, just to show you the added namespace for transactions):


    
    
    
    
    
     
    

Now all you need is to annotate you methods with adequate transaction annotations, for example:
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void saveUser(User user){
 userDao.save(user);
}
@Transactional(readOnly=true)
public User findUserByLoginOrEmail(String loginOrEmail) {
 return userDao.findUserByLoginOrEmail(loginOrEmail);
}
Here we have two types of annotations: a method that requires a new transaction to be opened (via propagation=Propagation.REQUIRES_NEW) and another one, that is only for reading DB data (via readOnly=true).
For a complete list of Spring transactions propagation behaviors please read this section of the docs.

Monday, July 8, 2013

JSF 2, Spring Security integration with Remember-Me (Contd.)

In last part, we said that we are going to use a database to store Remember-Me cookie's related data. This data consists of the username used to login, a series identifier and a token and a timestamp to maintain the last login to the app. For more details about the principles behind stored data, please refer to this article. Fortunately, for us, Spring Security will handle this stuff. We just need to give him the right configs.

1) Configuring database

First thing to do, is to prepare our database. In this series, I will be using MySQL as a DB. 
So let's create our table to store mentioned data:
create table persistent_logins (username varchar(64) not null,
      series varchar(64) primary key,
      token varchar(64) not null,
      last_used timestamp not null)
Next, we configure a datasource to be used, not only by Spring Security, but also by future persistence frameworks (Hibernate, Spring Data etc...). In applicationContext.xml add following:




First line, is just telling Spring about a properties file contained in classpath of our application and named "application.properties". This file, will contain config params that will help system administrators to deploy our application without any need to recompile whole application when a server password is changed:
db.driverClass=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/db_name_here
db.username=dbUserName
db.password=dbUserPassword
db.showSql=true

In next lines, we are just defining a Spring bean that will be our used JDBC datasource implementation. We need to pass it params like db url, username, driver class etc... Don't forget to add dependencies of your DB driver in POM file, for MySQL, just add following:


        mysql
 mysql-connector-java
 5.1.6

2) Remember-Me stuff

In previous part, we added a remember-me element to http config element. That will tell Spring Security to try to fetch user from our system whenever his browser send a valid cookie value.
Now we need to update that remember-me element so it references a new defined Spring bean:




     
    
    
    
    

The remember-me services bean must define an implementation of a remember-me strategy. Here I am going to use one of the two implementations Spring Security offers. For the PersistentTokenBasedRememberMeServices to work, we must give it: a tokenRepository which is a bean we will define and that will store tokens in previously created table, a userDetailsService (and we already defined one in previous part), a key that will be used to encrypt/decrypt sent cookie to client browser.  The two other properties are optional. And their names are just meaningful.
Now we define the tokenRepository bean:


 
     
     

We just give it the name of already configured datasource. The other property is just to prevent it to drop/create the table on each server start.

We need also to define an authentication provider related to the Remember-Me concept and register it:

 
   
   

And we need to register it in the authentication-manager already defined, here is the entire declaration:

    
     
    
    

And the last config we need is to define a Remember-Me filter that should intercept HTTP requests and validate cookies whenever needed:

     
     

Notice how we gave it references to our defined rememberMeServices and authenticationManager.

3) JSF 2 Remember-Me part

Now that everything is configured as expected, let's implement the JSF part of the app that should tell Spring Security when to remember a user, and when not.
First thing to do, is to inject the rememberMeServices service in the UserManagedBean managed bean:
@Inject
@Named("rememberMeServices")
private RememberMeServices rememberMeServices;
Next, in the login method in UserManagedBean class, we just add the following code:

HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();  
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
    @Override 
    public String getParameter(String name) { return "true"; }            
};  
rememberMeServices.loginSuccess(wrapper, response, authentication);
So what does this code do ? From the Spring Security docs, the RememberMeServices#loginSuccess method must be called "whenever an interactive authentication attempt is successful". And since we are doing login manually, then, we should invoke it manually. As for its role, this class "examines the incoming request and checks for the presence of the configured "remember me" parameter. If it's present, or if alwaysRemember is set to true, calls onLoginSucces". The onLoginSucces method by itself is responsible for creating a new persistent login token with a new series number. Then it stores the data in the persistent token repository and adds the corresponding cookie to the response. The loginSuccess method must be given a HttpServletRequest to check if a remember-me param is present and if it's equal to "true", if not it will just return. Second param is a HttpServletResponse, in which generated cookie is written, and finally a org.springframework.security.core.Authentication that will contain username of loggedin user. Now it should be clear why I overrided the getParameter method in the HttpServletRequestWrapper passed to loginSuccess. The added code by now, will activate the Remember-Me whenver called. This should not be the case, since not all users will wish their connections be maintained (they may connect from a public PC for example). This been said, we need to test if connecting user wants to be remembered:
//In user managed bean (where login method is defined)
private Boolean rememberMe = false;
and in the login page, we add a checkbox to let user decide:


Now we just test on the rememberMe value to decide whether to call RememberMeServices#loginSuccess or not. Et voilà!! We just finished with the Remember-Me feature in JSF 2 with Spring Security.
You can test your code by setting a session timeout value of 5 minutes for example, login to the application and wait for session to timeout and then re-call home page, you should access it without being obliged to re-login.

4) Instantiate JSF Managed beans

Now suppose, that with normal login, if user is successfully authenticated, you have a session managed bean that will handle some informations to be used by other managed beans in the application. You may say that we already have the logged in user's username in Spring Security' SecurityContextHolder. That's true, but also, the stored object has a few data, and you will soon be obliged to fetch more data for the User object from DB. That will result in extra DB access. 
So let's assume you have a managed bean like this: 
package com.raissi.managedbeans;

import java.io.Serializable;
import javax.inject.Named;
import org.springframework.context.annotation.Scope;
import com.raissi.model.User;

@Named("loggedInUser")
@Scope("session")
public class LoggedInUser implements Serializable{
 private static final long serialVersionUID = -1033377115353626379L;
 private User user;

 public User getUser() {
  return user;
 }

 public void setUser(User user) {
  this.user = user;
 }
}


We inject this bean in the UserManagedBean (view managed bean responsible for the login/logout process), and whenever a successful login takes place, we set user in LoggedInUser with the returned object from DB. And in all managed beans that need informations about user logged to the app, we just inject this managed bean.
Now if you try to access the application after session timeout, Spring Security will create a new session for you and authenticate you automatically. But in this newly created session, you won't have JSF session managed bean LoggedInUser. And if you try to access its User variable in a homeManagedBean, you will have a NullPointerException.
To initialize this bean, in early defined CustomUserDetailsService add the following code after setting authentication in SecurityContextHolder:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
LoggedInUser loggedInUser = (LoggedInUser)request.getSession().getAttribute("loggedInUser");
 if(loggedInUser == null){
         loggedInUser = new LoggedInUser();
  request.getSession().setAttribute("loggedInUser", loggedInUser);
 }
 if(loggedInUser.getUser() == null){
  loggedInUser.setUser(user);
 }
Thanks to Arjin comment below, this code will only work if the LoggedInUser objects are simple POJOs with no injected beans. But when we want to use other services inside it (as for example: injecting the RememberMeServices bean to centralize the updating process of SecurityContext, which I did indeed) then, things will go bad and complicated. And all of that if because of LoggedInUser object being manually instantiated.
The solution I opted for in this situation is to inject a scoped proxy of LoggedInUser inside CustomUserDetailsService. You would say, "but CustomUserDetailsService is a singleton service that will be created only once a time, however LoggedInUser is a session scoped bean, that will be created on every new session". And that's why I am using a scoped proxy of LoggedInUser. By that we will be "injecting a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real, target object from the relevant scope" (more details here). So how to do it ?
First let's create an interface that LoggedInUser will implement:
package com.raissi.managedbeans;

import java.io.Serializable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.raissi.domain.User;

public interface ILoggedInUser extends Serializable{

 public User getUser();
 public void setUser(User user);
 /**
  * Update security context
  * This method should be called whenever setUser is called.
  * It's defined here to be conform with the DRY principle.
  * @param request
  * @param response
  */
 public void updateSecurityContext(HttpServletRequest request, HttpServletResponse response);
}

After that let's change our LoggedInUser class:
package com.raissi.managedbeans;

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

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.stereotype.Component;

import com.raissi.domain.User;
import com.raissi.security.Authority;
import com.raissi.security.CustomUserDetails;
import com.raissi.util.UserRole;

@Component("loggedInUser")
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public class LoggedInUser  implements ILoggedInUser{
 private static final long serialVersionUID = -1033377115353626379L;
 
 @Inject
 @Named("rememberMeServices")
 private RememberMeServices rememberMeServices;
 
 private User user;

 public User getUser() {
  return user;
 }
 @PostConstruct
 public void init(){
 }
 public void setUser(User user) {
  this.user = user;
 }
 
 
 public void updateSecurityContext(HttpServletRequest request, HttpServletResponse response){
  List auths = new ArrayList();
  if(user.hasRole(UserRole.ADMIN.toString())){
   auths.add(new Authority("ROLE_ADMIN")); //Role here, like "admin"
   auths.add(new Authority("ROLE_USER"));
  }else {
   auths.add(new Authority(user.getRole())); //Role here, like "admin"
  }
  
  Authentication authentication =  new UsernamePasswordAuthenticationToken(new CustomUserDetails(user), null, auths);
  SecurityContextHolder.getContext().setAuthentication(authentication);
  
  HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
      @Override public String getParameter(String name) { return "true"; }            
  };
  rememberMeServices.loginSuccess(wrapper, response, authentication);
 }

}
Two things are to be noticed here:
a) we are using "proxyMode = ScopedProxyMode.INTERFACES" to tell Spring that we are exposing this bean as a proxy
b) we moved the logic to set authentication in Spring Security context from view managed beans (ex: in UserManagedBean) into the LoggedInUser.
This been done, you just update managed beans containing references to LoggedInUser to reference the new defined ILoggedInUser instead, example in UserManagedBean:
@Inject
private @Named("loggedInUser") ILoggedInUser loggedInUser;
And in login method:
//Get User object based on provided login and password:
User user = userService.loginUser(userLogin, password);
//Set user in LoggedInUser
loggedInUser.setUser(user);
//Update Security context:
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
loggedInUser.updateSecurityContext(request, response);

By now everything should work fine, and you completely have Spring Security working with your JSF 2 application and also with the Remember-Me feature activated

Thursday, July 4, 2013

JSF 2, Spring security integration with Remember-Me

Spring Security is a very powerful security framework. You can use it to manage application access both by defining Authentication and Authorization policies at both the web request level and at method invocation level. At the first level (request) Spring Security uses servlet filters. At the latter level (method), Spring Security uses Spring AOP-proxying objects and applying advice that ensures a particular user has the good rights to invoke a method.

1) Spring security Maven dependencies

To use the Spring Security framework at request level, we need to declare the "springSecurityFilterChain" at our web.xml. But first here are minimal dependencies to add in pom.xml file:


 org.springframework.security
 spring-security-core
 3.1.4.RELEASE



 org.springframework.security
 spring-security-web
 3.1.4.RELEASE



 org.springframework.security
 spring-security-config
 3.1.4.RELEASE

2) Spring security config

Now in web.xml:

 springSecurityFilterChain
 org.springframework.web.filter.DelegatingFilterProxy



 springSecurityFilterChain
 /*

The DelegatingFilterProxy filter by itself doesn't do much work. Instead, and as its name says, it delegates work to a defined bean in application context that will handle requests. For a matter of simplicity, I will separate my Spring files, into general application context beans and security ones. So in web.xml file, declare a context-param like this one:

 contextConfigLocation
 
 /WEB-INF/spring-security.xml
 /WEB-INF/applicationContext.xml
 

If defined, Spring will use this param to read config files and load defined beans. Now in spring-security.xml fil, we will define the specialized filter that will handle our security stuff:


 
  
   
  
 
 
  
 


Unlike in applicationContext file, here we are using beans:bean elements, this is because I chose the Spring Security namespace to be the default one. Notice that in the first declared bean, we are using the same bean name as the filter-name in web.xml for the DelegatingFilterProxy filter. This is very important. In fact, when finding a DelegatingFilterProxy filter, Spring security will automatically create a filter bean whose ID is: springSecurityFilterChain. This is the bean that will be responsible for security chaining. Once we defined which beans should be used for our security, we need to specify which URLs must be secured and which ones can be with public access:



 
 
 
 
 
 
 
 
 
 

Here for example, we decided that only users that have "ROLE_ADMIN" as role to access all "/admin/blah" pages. We also, excluded all paths containing "/javax.faces.resource/" from security checks. In fact, we don't want Spring Security to filter CSS or Javascript files. Now in the "form-login" element, we defined "/login" as login-page. Spring security will redirect non logged-in users to this page. remember-me and access-denied-handler will be discussed later, just ignore them by now.

3) Spring security authentication manager with custom user details

When designed, Spring Security was aimed to fetch by itself user credentials from DB or other data sources (LDAP etc...). To do that, you have to follow forms naming. Personnally, I prefer to manage Spring Security Context manually. This means, that it's up to me to tell Spring Security that a user has logged in. But even, in this way, you still need to define an authentication-manager:

    
    

Now you may notice that I gave to the authentication provider bean a reference to user-service. Well this is a " reference to a user-service (or UserDetailsService bean) Id". The custom user details service bean, must implement the UserDetailsService interface, which declares a single method to be implemented:
UserDetails loadUserByUsername(String username)
                               throws UsernameNotFoundException
So here is our CustomUserDetailsService class:
package com.raissi.security;

import javax.inject.Inject;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.raissi.model.User;
import com.raissi.service.UserService;

@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{

 @Inject
 private UserService userService;
 
 @Override
 public UserDetails loadUserByUsername(String login)
   throws UsernameNotFoundException {
  System.out.println("Trying to fetch user with login: "+login);
  final User user = userService.findUserByLoginOrEmail(login);
  if(user == null){
   throw new UsernameNotFoundException("User not found");
  }
  UserDetails details = new CustomUserDetails(user);
  Authentication authentication =  new UsernamePasswordAuthenticationToken(details, null, details.getAuthorities());
  SecurityContextHolder.getContext().setAuthentication(authentication);
  return details;
 }

}
The CustomUserDetails class by itself is implementing the UserDetails interface:
package com.raissi.security;

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

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.raissi.model.User;
import com.raissi.util.UserRole;

public class CustomUserDetails implements UserDetails{
 private static final long serialVersionUID = 2270217112782820892L;
 private User user;
 
 
 public CustomUserDetails(User user) {
  super();
  this.user = user;
 }
 @Override
 public boolean isEnabled() {
  return true;
 }
 @Override
 public boolean isCredentialsNonExpired() {
  return true;
 }
 @Override
 public boolean isAccountNonLocked() {
  return true;
 }
 @Override
 public boolean isAccountNonExpired() {
  return true;
 }
 @Override
 public String getUsername() {
  return user.getLogin();
 }
 
 @Override
 public String getPassword() {
  return user.getPassword();
 }
 @Override
 public Collection getAuthorities() {
  List auths = new ArrayList();
  if(user.hasRole(UserRole.ADMIN.toString())){
   auths.add(new Authority("ROLE_ADMIN")); //Role here, like "admin"
   auths.add(new Authority("ROLE_USER"));
  }else {
   auths.add(new Authority("ROLE_USER")); //Role here, like "admin"
  }
  return auths;
 }
}
Next thing to do, is to define our GrantedAuthority objects. In fact, these objects will be used by Spring Security to know which role does user have(Remember in first step, we defined roles for users to access particular pages). So here are our very simple Authority implementation:
package com.raissi.security;

import org.springframework.security.core.GrantedAuthority;

public class Authority implements GrantedAuthority{
  private static final long serialVersionUID = 9170140593525051237L;

  private String authority;

  public Authority(String authority) {
    super();
    this.authority = authority;
  }

  @Override
  public String getAuthority() {
    return authority;
  }
  @Override
  public String toString() {
    return "Authority [authority=" + authority + "]";
  }

}

Until now, we are just doing Spring Security in the standard way. The only difference we will make, is how setting the security context will go. In second part of this series, we defined a ManagedBean (Named UserManagedBean) that handles user login via "login()" method. Now, in that method, just add following lines, before returning home page:
List auths = new ArrayList();
  if(user.hasRole(UserRole.ADMIN.toString())){
   auths.add(new Authority("ROLE_ADMIN")); //Role here, like "admin"
   auths.add(new Authority("ROLE_USER"));
  }else {
   auths.add(new Authority("ROLE_USER")); //Role here, like "admin"
  }
  
  Authentication authentication =  new UsernamePasswordAuthenticationToken(new CustomUserDetails(user), null, auths);
  SecurityContextHolder.getContext().setAuthentication(authentication);  
Et voilà! Now if you start server, and try to access any page except the login page, you will be redirected to login page.

4) Spring security custom access denied page

For now, if you login as simple user with "ROLE_USER" to the application, and then try to access an admin page, you will get an ugly Tomcat 403 page, which mentions that you are not authorized to see this page. A good point would be to customize this page. Remember from part 2 in this article that we used a "access-denied-handler" balise in our config. Well, this refers to a custom bean that we are defining to handle non authorized access: 
package com.raissi.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

/**
 * Custom Access denied handler, called in the spring-security config
 *
 */
@Component("customAccessDeniedHandler")
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
 
 public CustomAccessDeniedHandler() {
 }
 
 @Override
 public void handle(HttpServletRequest request, HttpServletResponse response,
      AccessDeniedException accessDeniedException) throws IOException, ServletException {
    response.sendRedirect(request.getContextPath()+"/accessdenied");
    request.getSession().setAttribute("message",
  "You do not have permission to access this page!");
 
 }
 
}
As you can see, here we are just implementing the AccessDeniedHandler interface which defines a single method. This method will be called by Spring Security every time a non authorized user is trying to access some forbidden places.
In this method, we are redirecting user to a path named "accessdenied" under root path. So using Prettyfaces we will define this path. If you are not using Prettyfaces, you are free to define the path you want to use.

    
    

For the accessdenied.xhtml page, it will just contain a simple message indicating that user is not authorized to see this content. You can use the message we set in session attribute "message".

5) Spring Security Remember-Me with JSF 2

Almost every login based application in the world offers to user the possibility to stay logged in the system when connecting from the same machine and same browser. This is as you may guessed, the "Remember-Me' feature, and happily it's supported by Spring Security. 
To do this, we will use a DB (yes, a DB, for the first time in these series) to store data related to user being logged in and his remember me cookie.
Please follow next part to continue with remember me implementation.

Tuesday, June 25, 2013

JSF 2 tutorial. Part II: Spring integration and Prettyfaces usage

In the first part of this JSF 2 series, we prepared our development environment: Eclipse, Maven, Tomcat 7 and JSF 2. In this second part, we will walk through Spring integration with JSF 2. We will also see how to use the Prettyfaces library. And finally we will use Spring security to secure the access to our application.

1) Spring integration

First we need to add Spring dependencies to our application (POM file):
3.2.3.RELEASE



 javax.inject
 javax.inject
 1



  org.springframework
  spring-core
  ${org.springframework.version}



  org.springframework
  spring-expression
  ${org.springframework.version}

 


  org.springframework
  spring-beans
  ${org.springframework.version}



  org.springframework
  spring-aop
  ${org.springframework.version}

 


  org.springframework
  spring-context
  ${org.springframework.version}

 


  org.springframework
  spring-context-support
  ${org.springframework.version}



  org.springframework
  spring-tx
  ${org.springframework.version}



  org.springframework
  spring-web
  ${org.springframework.version}



 org.springframework
 spring-orm
 ${org.springframework.version}


You can refer to this blog entry from Spring source for detailed explanation about every dependency.
Next step is to create the famous Spring's applicationContext.xml file:


 
 
 
 
 

  
Now we need to register Spring listeners in the web deployment descriptor:




 org.springframework.web.context.ContextLoaderListener



 org.springframework.web.context.request.RequestContextListener

Last config to be done, is registering the SpringBeanFacesELResolver in the faces-config.xml file:

   
   
  
          org.springframework.web.jsf.el.SpringBeanFacesELResolver
  
   

The SpringBeanFacesELResolver is an ELResolver that delegates to the Spring root WebApplicationContext, resolving name references to Spring-defined beans.
Now we can use the Spring framework for dependency injection (DI) in our application. If you are not familiar with DI and Inversion of Control (IoC) please refer to this excellent article.
In the first part of this series, we annotated our user managed bean with:
@ManagedBean(name="userManagedBean")
@SessionScoped
to make JSF aware of it. Now we want Spring to be responsible for missions like this: registering all components and instantiating them when needed. For this, Spring offers multiple class annotations: @Component, @Service, @Repository.
So we change our UserManagedBean to be annotated with:
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("session")
public class UserManagedBean implements Serializable
By now you can start your server and see that the bean is instantiated.

2) JSF2 View scope with Spring

JSF 2 introduced a big enhancement by introducing new scopes to Managed beans. One of the most interesting scopes, is the View scope. In fact, if you used JSF 1.2 without Richfaces (or Seam), then you would have found yourself obliged to define most of your managed beans as Session beans, otherwise you would encounter plenty of problems with Ajax requests sent along with request scoped beans. In fact, with every Ajax call, request bean is re-instantiated again.
With the View scope, your bean will keep alive (this remembers me the a4j:keepAlive in Richfaces) until view is completely refreshed.
The problem here with Spring, is that you can not define a bean with @Scope("view") by default. An excellent workaround was proposed by Cagatay Civici (Founder of Primefaces) here.
The main idea, is to define the View scope our self and make Spring aware of it and add it to its list of scopes.
So first thing to do is to define the ViewScope class that implements the Scope interfaces:

package com.raissi.spring.customscope;

import java.util.Map;

import javax.faces.context.FacesContext;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

/**
 * Implements the JSF View Scope for use by Spring. 
 * This class is registered as a Spring bean with the CustomScopeConfigurer.
*/
public class ViewScope implements Scope {

 public Object get(String name, ObjectFactory objectFactory) {
  if (FacesContext.getCurrentInstance().getViewRoot() != null) {
   Map viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
   if (viewMap.containsKey(name)) {
    return viewMap.get(name);
   } else {
    Object object = objectFactory.getObject();
    viewMap.put(name, object);
    return object;
   }
  } else {
   return null;
  }
 }

 public Object remove(String name) {
  if (FacesContext.getCurrentInstance().getViewRoot() != null) {
   return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
  } else {
   return null;
  }
 }

 public void registerDestructionCallback(String name, Runnable callback) {
  // Do nothing
 }

 public Object resolveContextualObject(String key) {
  return null;
 }

 public String getConversationId() {
  return null;
 }

}
Once done, we need to register our newly defined scope to the Spring CustomScopeConfigurer in applicationContext.xml:


 
  
   
    
   
  
 

And that's all you need to make Spring aware of ViewScope. Notice that possible enhancements to this workaround can be found here for possible memory leaks. Et voilà!!! vous avez Spring et JSF 2 ready to go. Next step is to prettify our URLs.

3) Using Prettyfaces

Prettyfaces is an open source URL-rewriting library used essentially with JSF (1.1, 1.2 and 2). It's a very powerful library to re-write your JSF app URLs with many customization features. It's also very easy to configure and use. First thing, add Prettyfaces dependencies in your POM file: 

 com.ocpsoft
 prettyfaces-jsf2
 3.3.3

Next, configure your web.xml to use the Prettyfaces filter:

  Pretty Filter
  com.ocpsoft.pretty.PrettyFilter
  true


 
  Pretty Filter 
  /* 
  FORWARD 
  REQUEST 
  ERROR
  ASYNC

Last thing is to map your views with Prettyfaces. So under WEB-INF, create a file pretty-config.xml:


 
  
  
 
 
  
  
  #{userManagedBean.logout}
 
 
  
  
 


As you can see in this mapping file, to prettify your URLs you need to create a url-mapping for each JSF view. For example, if we want the URL to login page to be just: http://domainname.ex/login instead of http://domainname.ex/pages/login.jsf then we create a url-mapping, defining "/login" as pattern and /pages/login.jsf as correspondent view. So whenever there is a call to /login URL the "/login/login.jsf" view will be rendered. Now, we want that whenever the "/logout" URL is called by browser, user is a) redirected to login.jsf and b) also user session is destroyed. This can be easily achieved by defining the pattern /logout pointing to login.jsf view and also we define an action element. This action, is just a method of a defined managed bean that will get executed once the specified URL is called. And here is our method:
public void logout(){
     FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
}
Other beautiful features can be found in the Prettyfaces user guide.
In next part of the series, we will add some security to our application