Monday, August 01, 2011

SSL in Tomcat under Eclipse (part 1 - self signed certificate)

Requirements:
  • installed Java (description here)
  • installed and configured Eclipse (description here)
  • installed and configured Tomcat for the Eclipse (description here)
You will learn:
  • how to set up Tomcat for SSL connection using self signed certificate under Eclipse
When You want to secure Your application SSL is the most natural choice. In order to make Your application be recognized as trusted by browser, You can by a buy a certificate from well known certificate authority (CA), which will be generated for the domain Your application uses. If You do not care about being recognized as trusted service, but instead You just want to encrypt the data exchanged between server and client's browser, You can use Your own self signed SSL certificate. In this post I will show how to generate such SSL certificate and how to set up Tomcat (from the Eclipse level) to use generated certificate.

Note: let's assume that You created an application which is going to be visible under the following URL: http://www.myapp.com.

Step 1: generating self signed certificate for domain www.myapp.com.

Go into Your Java bin directory (i.e C:\Development\Java\bin). Then open Windows console (under Windows Vista/7 open the console with Administrator right) and type in command:

keytool -genkey -alias myappcert -keyalg RSA -keystore myapp.keystore

where myappcert is the name of the certificate being generated and myapp.keystore is a file where certificate will be stored. You will be asked about the password for created the myapp.keystore file. Type in "mypass", press Enter and type it again and press Enter again. Then You will be asked for some details about You:



Please note that for the first question about first and last name I gave answer www.myapp.com. This is very important - this name (known as CN - Common Name) will be used for the checking if certificate on the page we visit was generated for the same URL which we typed in in the browser.
At the end You will be asked for the password for the newly created certificate. The password must be the same as one used for myapp.keystore file ("mypass"). Do not type antyhing, just press Enter to use the same password. Your myapp.keystore file containing myappcert certificate is ready.

Step 2: copy Your myapp.keystore file into Tomcat's /conf directory

Step 3:  modify Tomcat configuration to use SSL certificate.

Make sure that Your Tomcat is configured with Eclipse and works OK without SSL (start Tomcat from Eclipse and type in http://localhost:8080 in the browser). Stop Tomcat if it is running. Then open server.xml file form the "Servers" view:



and locate default element for standard HTTP connections (marked red). Then add additional element for the SSL connection (next to existing one):
<Connector
        SSLEnabled="true"
        clientAuth="false"
        keyAlias="myappcert"
        keystoreFile="conf/myapp.keystore"
        keystorePass="mypass"
        maxThreads="200"
        port="8081"
        scheme="https"
        secure="true"
        sslProtocol="TLS"
 /> 

Please note that next to some specific SSL settings, we set the location of the keystore file, the password for that file and certificate name to be use. SSL connection uses port 8081, where normal HTTP connection
uses port 8080.

Note 1: all modification of server.xml file were done from Eclipse level, using "Servers" view. If You want to use Eclipse WTP for starting Tomcat (like I do so far) You can't edit this file from elsewhere. Eclipse WTP overrides original Tomcat configuration files by files visible under "Servers" - changes done outside Eclipse will not be visible for WTP.

Note 2: I added element specific for SSL next to existing element for standard non encrypted HTTPS connections. This is second issue directly connected with Eclipse WTP - when You remove standard connector for HTTP, Eclipse will close Tomcat after a time set in "Timeouts" section in the Tomcat settings:



Some people try to extend the timeout time into long period, but still after this period Eclipse kills Tomcat process, as if Tomcat was not properly started in the required time. Unfortunately there is no way to set timeout into ifinite time - the only way to fix this under WTP is to leave standard HTTP element in Tomcat's server.xml file.

Step 4: that's all. Tomcat is configured to work with SSL. 

Try to enter the URL: https://localhost:8081. If You see Tomcat's page, everything works OK (You can see certificate warning - You Need to add security exception for that certificate). Of course You can still open the same Tomcat page by standard HTTP (You have two elements), just enter http://localhost:8080 URL.

Wednesday, July 27, 2011

Tomcat OutOfMemoryError: Heap space/PermGen space

Note: below description uses Tomcat 7.0.28

Have You ever seen such error in Your logs? Probably yes. It simply means that available memory for Tomcat was consumed and nothing left. To be precise: available memory for JVM which Tomcat uses to run.

What causes this error? It can be caused by memory leaks in the application or the applications has big requirements "by design", even if there are no memory leaks. For the first case You should use some profiling tools to find and fix memory leaks - perhaps this might help without need to change memory settings for Tomcat JVM. If You are sure that Your application has no memory leaks, the only way is to increase memory used by Tomcat JVM. See below how to do that - please note that I described modifying Tomcat memory settings when it is installed as a service under Windows OS.

32-bit Windows
The main problem here is that 32-bit OS is able to see no more than 3,2GB of RAM, even if You have 4GB or more physically installed. This is upper limit of memory that can be use - in theory. However, in practise You will not be able to use more than 1 to 1,5GB of RAM for Tomcat's JVM - the rest of memory is used by OS itself and installed software.

64-bit Windows
Let's assume that You need to assign more than 1,5GB of RAM for Tomcat JVM. Therefore You need 64-bit OS with at least 4GB of RAM (for example 64-bit Windows Professional supports up to 192GB of RAM). Of course You must also use 64-bit JDK - when You use 32-bit JDK under 64-bit OS, You will again face the limit of 3,2GB RAM. You also must use 64-bit version of Tomcat (as it contains Windows service wrapper to use with 64-bit JVMs on 64-bit Windows platforms). Below You will find complete list of all needed steps:

Step 1: make sure You are using 64-bit Windows OS. 

Step 2: install 64-bit JDK and set $JAVA_HOME to the installation directory. 

Step 3: download .zip file with 64-bit Tomcat for Windows (file: apache-tomcat-[version]-windows-x64.zip). 

Step 4: extract Tomcat and go into Tomcat's /bin directory.

Step 5: open service.bat file and locate the line with --JvmMS and --JvmMX parameters, and modify it with new values memory, eg:

%EXECUTABLE%" //US//%SERVICE_NAME% ++JvmOptions "-Djava.io.tmpdir=%CATALINA_BASE%\temp" ++JvmOptions "-XX:MaxPermSize=1024m" --JvmMs 2048 --JvmMx 4096

Note: PermSize is set in different way than heap which has predefined JvmMS and JvmMX flags.

Step 6: open Windows console with administrator rights, then go into Tomcat /bin and execute command:

service.bat install tomcat6

Step 7: start service with command:

net start tomcat6

Note 1: You can skip point 5 and execute directly point 6. After that just start tomcat6w.exe which is a GUI tool for managing the service. You can set memory values there.

Note 2: as an alternative to above steps, You can download Tomcat service installer (file: apache-tomcat-[version].exe) which performs service installation, and then use tomcat6w.exe tool for tune memory settings.

That's all. Your Tomcat service should use provided memory settings.

Sunday, May 22, 2011

PostgreSQL - strange database server errors under Windows

I often use PostgreSQL as a database server for my web applications which are usually deployed under Tomcat. PostgreSQL and Tomcat are registered as system services which starts automatically when Windows starts. 

In one of my application I have about 50 different databases with connection pools for each database, where each pool has about 10 connections opened. So I have about 500 connections opened for requests. Each opened connection is visible as a separate postgres.exe process in the system next to the own PostgreSQL processes also visible as postgres.exe (usually 5 processes). Sometimes under Windows XP Prof. SP 3 I saw PostgreSQL stop working and in the server logs there were errors like:
  •  java.net.SocketException: No buffer space available (maximum connections reached?): recv failed
or:  
  • server process (PID XXXX) was terminated by exception 0xC0000142 HINT:  See C include file "ntstatus.h" for a description of the hexadecimal value.
--------------------------------------------
No buffer space available error:

"Maximum connection reached" may suggest that we set too low value of max_connections in postgresql.conf file. Let's assume that settings for connections amount and required memory are OK for the server, but the problem is still visible from time to time.

The first thing to be checked is amount of short-lived ports (ephemeral). Those ports are used by applications during their normal work. They are opened and live until certain application works, in comparison to server application ports that are typically open for the entire time that the server computer is running. They are assigned automatically from predefined range. Range differs between operating systems:

a) Windows 2000 -> from 1024 to 5000
b) Windows 2003 Server -> from 1024 to 5000
c) Windows XP (all service packs) -> from 1024 to 5000
d) Windows Vista -> from 49152 to 65535
e) Windows 2008 Server -> from 49152 to 65535
f) Windows 7 -> from 49152 to 65535
g) Linux kernels -> from 32768 to 61000 (see /proc/sys/net/ipv4/ip_local_port_range)

If the available pool of ephemeral ports is exahsuted we see Windows WSAENOBUFS error (no buffer space, code 10055). In order to check for exceeded range, we have to see how many processes are running in the system and how many ports they are opening - we can use free TCPView application. We can kill the process that causes exceeding or we can increase the range of ephemeral ports. If we want to increase it, we have to change a registry entry named maxUserPort in:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\maxUserPort
 
If that registry entry does not exist it means that system uses default value (see above) and we have to create this entry. Then we have to set a proper value for that entry (REG_DWORD) from the range 5000 to 65534. 

The second thing to be checked is limit of half-opened TCP/IP connections (connection with state SYN-RCVD). When this limit is exceeded, TCP/IP starts up SYN flooding attack protection (when SynAttackProtect is enabled). This limit differs between operating systems:

a) Windows 2000 Workstation -> 500
b) Windows 2000 Server -> 100
c) Windows Server 2003 -> 500 
d) Windows XP SP 1 -> 100
e) Windows XP SP 2, SP3 -> 10
f) Windows Vista SP 1 -> 10
g) Windows Vista SP 2 -> limit removed (not implmented = unlimited)
h) Windows Server 2008 SP 1 -> 10
i) Windows Server 2008 SP 2 -> limit removed (not implemented = unlimited)
f) Windows 7 -> limit removed (not implemented = unlimited) 

We can use mentioned TCPView application to check for half-opened TCP connections. This limit can be increased by changing the registry entry named TcpMaxHalfOpen in:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpMaxHalfOpen

If that registry entry does not exist it means that system uses default value (see above) and we have to create this entry and then manualy assign new value.

Under Windows Vista SP2, Windows 7 or Linux I did not see that error.

--------------------------------------------
0xC0000142 error:

This problem is not so easy to explain, although I was able to fix it. The error code means that "A dynamic link library (DLL) initialization routine failed." I am not sure what exacly causes this... 

In my case under Windows XP Prof. SP 3, when I started my application and number of postgres.exe processes was about 100 (it should be about 500, see description at the top) the whole database server process was suddenly terminated and I saw second mentioned error (with error code 0xC0000142) in the logs. The most important part here is that PostgreSQL service, which spawned many postgres.exe child processes, was registered under LOCAL SYSTEM account, without "Allow Service to Interact with Desktop" option set.

It seems that this problem is not only connected with PostgreSQL. It is general problem with services and their subprocesses (see this and that article). From the information found the problem my be connected with so-called desktop heaps (see more here and here). Some people having similar problems with many subprocesses did the workaround by setting "Allow Service to Interact with Desktop" to true for their LOCAL SYSTEM services. I was able to fix it under Windows XP Prof. SP 3, by registering PostgreSQL service for regular user account instead of LOCAL SYSTEM (see "Long Version" from my article about manual installation of PostgreSQL how to do this). I also checked this under Windows Vista SP2 and Windows 7 - it works OK there, even under LOCAL SYSTEM account. Under Linux I did not see that error.

I did not try to assign more desktop heap from default for Windows XP SharedSection=1024,3072,512 (2nd or 3rd value needs to be changed) and then try it again to run under LOCAL SYSTEM without "Allow Service to Interact with Desktop". Perhaps this might also help.

Tuesday, April 26, 2011

JSF 2, Spring 3, JPA (Hibernate 3), PostgreSQL, c3p0 - everything together (part 2 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 2.1.7, Spring Framework 3.1.1, Spring Security 3.1.0, Hibernate 3.6.10 (Final), PostgreSQL 9.1.

Requirements:
  • running database and complete project with all required libraries integrated, described in previous post (can be found here)

Step 4 (continued): configuration files - faces-config.xml.

Comparing to a JSF 2.0 project with Spring integrated, only applicationContext.xml file will be changed - web.xml and faces-config.xml files will be the same. We need to add below code into applicationContext.xml:
<bean id="pooledDataSource" 
 class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
 <property name="driverClass" value="org.postgresql.Driver" />
 <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/bikes"/>  
    <property name="user" value="postgres"/>  
    <property name="password" value="pgpass"/> 
    <property name="maxPoolSize" value="10" />
 <property name="maxStatements" value="0" />
 <property name="minPoolSize" value="5" />  
</bean>
 
<bean id="JDBCDataSource" 
 class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
 <property name="driverClassName" value="org.postgresql.Driver"/>
 <property name="url" value="jdbc:postgresql://localhost:5432/bikes"/>
 <property name="username" value="postgres"/>
 <property name="password" value="pgpass"/>
</bean>
 
<bean id="entityManagerFactory"
 class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="jpaVendorAdapter">
  <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
   <!-- 
   Specific properties for Hibernate are in persistence.xml file, 
   but also can be placed here and removed from persistence.xml file.  
   -->
  </bean>
 </property>
 <property name="dataSource" ref="pooledDataSource" />
 <property name="persistenceUnitName" value="persistenceUnit"/> 
</bean>

<bean 
 class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<bean name="transactionManager" 
 class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />  
</bean>

<tx:annotation-driven />
Note that this approach is similar to situation when plain Hibernate API is used with Spring: JPA's EntityManagerFactory is like Hibernate's SessionFactory, JPA's EntityManager (obtained from EntityManagerFactory) is like Hibernate's Session (obtained from SessionFactory). JPA's EntityManager is injected into Repositories (with the help of Spring's PersistenceAnnotationBeanPostProcessor class), while Hibernate's Session was injected into DAO's (with the help of Spring's HibernateDaoSupport class exteneded by each DAO). JPA's TransactionManager (built on EntityManagerFactory) is like Hibernate's HibernateTransactionManager (built on SessionFactory).
JPA's Repositories and Services are similar to oldschool DAOs and Facades. Repositories are injected into Services, while DAOs are injected into Facades.

Please note that I defined here two datasources: a basic one without connection pool (JDBCDataSource) and second one using c3p0 as a connection pool (pooledDataSource).


Step 5: configuration files - persistence.xml

In addition JPA uses a special configuration file named persistence.xml. This file contains additional settings for JPA vendor. The location of this file is described in this article. In order to have this file inside WEB-INF/classes/META-INF/persistence.xml under Eclipse, I created a directory "config" where I put META-INF subdirectory with persistence.xml file inside. Then I select the directory "config" to be used as a source directory. This means that content of "config" directory will be on classpath, and for a web application during a build time it will be moved into WEB-INF/classes. Note that I also added there log4j config file:




Persistence.xml file contains some specific settings for Hibernate (as JPA vendor):
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
 version="1.0">

 <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
  <properties>   
     <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
     <property name="hibernate.show_sql" value="true" />
    </properties> 
 </persistence-unit>
</persistence>


Step 6: configuration files - log4j.properties


As I wrote before we will use Log4j instead of Hibernate's default SLF4j. Lets's log everything we can (we can see how Hibernate opens/closes connections, how connections are taken from the pool, how Spring manages transactions and so on):
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
log4j.rootLogger=info,A1

log4j.logger.com.mchange.v2=DEBUG 
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.springframework=DEBUG

Step 7: database entities.

As shown at the beginning of previous post, we had only one entity represented by the class Bike.java. Instances of Bike.java where created inside Spring service named bikeDataProvider (BikeDataProviderImp.java). Now we have a database with tables Bike, Bike_Category, Account and Role. For each table we should create one class (note: this is the simplest mapping one table to one class - there are other way to map tables to classes).


Bike entity:
package com.jsfsample.model;

@Entity
@Table(name="bike")
public class Bike implements Serializable {

 private Integer id;
 private BikeCategory category; 
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)     
 @Column(name="bike_id")
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 
 @ManyToOne
 @JoinColumn(name="bike_category_id") 
 public BikeCategory getCategory() {
  return category;
 }
 public void setCategory(BikeCategory category) {
  this.category = category;
 }
 
 // rest of columns
}
Bike_category entity:
package com.jsfsample.model;

@Entity
@Table(name="bike_category")
public class BikeCategory {
 
 private Integer categoryId;
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="bike_category_id")
 public Integer getCategoryId() {
  return categoryId;
 }
 public void setCategoryId(Integer categoryId) {
  this.categoryId = categoryId;
 }
 // rest of columns
}
Account entity:
package com.jsfsample.model;

@Entity
@Table(name="account")
public class Person {
 
 private Integer accountId;
 private Role currentRole;
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="account_id")
 public Integer getAccountId() {
  return accountId;
 }
 public void setAccountId(Integer accountId) {
  this.accountId = accountId;
 }
 
 @ManyToOne
 @JoinColumn(name="role_id") 
 public Role getCurrentRole() {
  return currentRole;
 }
 public void setCurrentRole(Role currentRole) {
  this.currentRole = currentRole;
 }
 // rest of columns 
}
Role entity:
package com.jsfsample.model;

@Entity
@Table(name="role")
public class Role {

 private Integer roleId;
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="role_id")
 public Integer getRoleId() {
  return roleId;
 }
 public void setRoleId(Integer roleId) {
  this.roleId = roleId;
 }
 // rest of columns
}
Note how classes are mapped to tables (using @Table(name="...")) and how fields are mapped to columns (using @Column(name="...")). We also mapped many-to-one relations between tables using @ManyToOne annotation with proper joim column name. Note also how primary keys are generated - we do not use PostgreSQL sequence (GenerationType.SEQUENCE) - PostgreSQL supports SERIAL data type for primary keys, which actually hides sequences (see this link).

Step 8: repositories and services.

Spring repositories are similar to DAO. All database interactions is done insde them. As an example, let's look inside repository resposnible for loading and saving bikes - BikesDAOImpl.java:


package com.jsfsample.repositories.impl;

@Repository("BikesRepository")
public class BikesDAOImpl implements BikesDAO {
 
 private EntityManager em = null;
 
 @PersistenceContext
 public void setEntityManager(EntityManager em) {
  this.em = em;
 }
 
 @Override
 public Bike loadSelectedBike(Integer bikeId) {
  return em.find(Bike.class, bikeId);
 }
 // other methods for saving bike and loading bike for given category

}

This repository is used in Spring's service named bikeDataProvider (BikeDataProviderImpl.java):


package com.jsfsample.services.impl;
...
@Service("bikeDataProvider")
public class BikeDataProviderImpl implements BikeDataProvider {

 @Resource(name="BikesRepository")
 private BikesDAO bikesRepository;
 
 @Resource(name="DictionaryRepository")
 private DictionariesDAO dictionaryRepository;

 public Bike getBikeById(Integer id){
  return bikesRepository.loadSelectedBike(id);
 }
 
 @Transactional
 public void add(Bike newBike, Integer categoryId) {
  BikeCategory categorySelected = dictionaryRepository.loadBikeCategroryById(categoryId);
  newBike.setCategory(categorySelected);
  bikesRepository.saveBike(newBike);
 } 
 
 // other methods using repositories
}
Similar solution is used for account (person) repository which is then used in Spring's Security service named userDetailsService (UserDetailsServiceImpl.java). Note how easy is to execute a method within database transaction - just use @Transactional annotation and voila.

That's all about adding JPA into Spring-based JSF2 sample application.

The rest of application code (web pages, JSF managed beans) are the same as in pure Spring example project - we only modified services by providing repositories.

How to test it? After deploying application on the server and starting the server, we have to open a browser and type in URL:

http://localhost:8080/JSF2FeaturesSpringJPA



-------------------------------------------
Download source files:
Note: make sure that Java, Eclipse and Tomcat are properly installed and configured for running the project (additional configuration may be required if different directories are used).

Eclipse complete sample project is here (with all required libraries). The sample project is a ready to run application which contains JPA (Hibernate), Spring (with Spring Security). You can also download a war file located here (just copy it inside webapps folder in Your Tomcat and start Tomcat with the script startup.bat). Make sure that before doing this You created required database and PostgreSQL server is up and running (You can check access using pgAdmin III).

Wednesday, March 09, 2011

JSF 2, Spring 3, JPA (Hibernate 3), PostgreSQL, c3p0 - everything together (part 1 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 2.1.7, Spring Framework 3.1.1, Spring Security 3.1.0, Hibernate 3.6.10 (Final), PostgreSQL 9.1.

Requirements:
  • a working example of JSF 2.0 application with Spring Framework and Spring Security integrated (can be found here)
  • installed PostgreSQL database (simple installation variant described here)
You will learn:
  • how to use database for loading and storing the data in the sample JSF 2.0  application
  • how to access the database from the application using JPA (Hibernate) and Spring
  • how to optimize database access by using connection pool (c3p0)
It is a high time to create a real working example with a database. Sample application used in previous posts use no database. We had Spring's managed service named bikeDataProvider acting as a database - all bikes data were created in that service during startup, all bikes data were retrieved from that service, even new bike data were stored internally in the service:
package com.jsfsample.services.impl;
...
@Service("bikeDataProvider")
public class BikeDataProviderImpl implements BikeDataProvider {

 private List<Bike> bikes;

 @PostConstruct
 private void prepareData(){
  bikes = new ArrayList<Bike>();
  
  // MTB
  Bike mtb1 = new Bike();
  mtb1.setId(1);
  mtb1.setName("Kellys Mobster");
  mtb1.setDescription("Kellys Mobster, lorem ipsut...");
  mtb1.setPrice(6500);
  mtb1.setCategory(1);
  
  // ... rest of mock bikes created here
 }
 
 public List<Bike> getBikesByCategory(Integer categoryId, boolean onlyWithDiscount) {
  // returns bikes by given category
 }
 
 public Bike getBikeById(Integer id){
  // returns certain bike for its details
 }

 @Override
 public void add(Bike newBike) {
  // add new bike 
  bikes.add(newBike);
 }
}
The same method of creating mock data was used in Spring's managed service named userDetailsService - users and their authorities were created directly inside the service:
package com.jsfsample.application.impl;
...
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

 private HashMap<String, org.springframework.security.core.userdetails.User> users = new HashMap<String, org.springframework.security.core.userdetails.User>();
 
 @Override
 public UserDetails loadUserByUsername(String username) {
  // returns user
 }

 @PostConstruct
 public void init() {
  
  // mocked roles  
  Collection<GrantedAuthority> adminAuthorities = new ArrayList<GrantedAuthority>();
  adminAuthorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
  
  Collection<GrantedAuthority> userAuthorities = new ArrayList<GrantedAuthority>();
  userAuthorities.add(new GrantedAuthorityImpl("ROLE_REGISTERED"));
  
  boolean enabled = true;
  boolean accountNonExpired = true;
  boolean credentialsNonExpired = true;
  boolean accountNonLocked = true;
  
  // mocked users with roles
  users.put("admin", new org.springframework.security.core.userdetails.User("admin", "admin", enabled, accountNonExpired,
    credentialsNonExpired, accountNonLocked, adminAuthorities));
  
  users.put("user", new org.springframework.security.core.userdetails.User("user", "user", enabled, accountNonExpired,
    credentialsNonExpired, accountNonLocked, userAuthorities));
 }
}
In both cases all data are created in the method annotated with @PostConstruct. That annotation means, that method will be invoked first after creating an instance of a class (in this case Spring creates instances of those service classes).

Our objective is to remove that mocked data created explicite in the services classes and replace them with data coming from real database.

Step 1: we need database structure:
CREATE TABLE "role" (
 role_id SERIAL NOT NULL,
 name VARCHAR(32),  
 CONSTRAINT role_pk PRIMARY KEY (role_id)
);

CREATE TABLE "account" (
 account_id SERIAL NOT NULL,
 role_id INTEGER NOT NULL,
 login VARCHAR(32),
 password VARCHAR(32),
 CONSTRAINT account_pk PRIMARY KEY (account_id),
 CONSTRAINT role_id_fk FOREIGN KEY (role_id) REFERENCES role(role_id)
);

CREATE TABLE "bike_category" (
 bike_category_id SERIAL NOT NULL,
 name VARCHAR(32),  
 CONSTRAINT bike_category_pk PRIMARY KEY (bike_category_id)
);

CREATE TABLE "bike" (
 bike_id SERIAL NOT NULL,
 bike_category_id INTEGER NOT NULL,
 name VARCHAR(32),
 description TEXT,
 price numeric(10,2),
 discount_price numeric(10,2),    
 CONSTRAINT bike_pk PRIMARY KEY (bike_id),
 CONSTRAINT bike_category_fk FOREIGN KEY (bike_category_id) REFERENCES bike_category(bike_category_id)
);
This is very simple database with two many-to-one relations: many users belongs to (have) one role and many bikes belongs to (have) one category. Of course in real world user would have many roles, so we would use many-to-many relation, but I decided to use many-to-one to simplify it.
Tables account and role will be used by Spring Security - they store users and their authorities (roles). Tables bike and bike_category are the "heart" of bike store.

Step 2: when structure is ready, it is time to insert some sample data:
INSERT INTO role (name) values ('ROLE_ADMIN'); -- id 1
INSERT INTO role (name) values ('ROLE_REGISTERED'); -- id 2

INSERT INTO account (role_id, login, password) values (1, 'admin', 'admin'); -- ROLE_ADMIN
INSERT INTO account (role_id, login, password) values (2, 'user', 'user'); -- ROLE_REGISTERED

INSERT INTO bike_category (name) values ('Mountain'); -- id 1
INSERT INTO bike_category (name) values ('Trekking'); -- id 2
INSERT INTO bike_category (name) values ('Cross'); -- id 3

INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (1, 'Kellys Mobster', 'Kellys Mobster, lorem ipsut...', 6500, null); -- Mountain
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (1, 'Scott Scale', 'Scott Scale, lorem ipsut...', 18900, null); -- Mountain
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (1, 'Author Magnum', 'Author Magnum, lorem ipsut...', 17200, 15500); -- Mountain

INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (2, 'Giant Accend', 'Giant Accend, lorem ipsut...', 5000, 4600); -- Trekking
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (2, 'Merida Freeway', 'Merida Freeway, lorem ipsut...', 2400, 2100); -- Trekking
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (2, 'Mbike Massive', 'Mbike Massive, lorem ipsut...', 1900, null); -- Trekking

INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (3, 'Giant Roam XR 1', 'Giant Roam XR 1, lorem ipsut...', 3900, null); -- Cross
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (3, 'Cannondale Quick Cx', 'Cannondale Quick Cx, lorem ipsut...', 4999, null); -- Cross
INSERT INTO bike (bike_category_id, name, description, price, discount_price) values (3, 'Cube Cross', 'Cube Cross, lorem ipsut...', 4500, 4200); -- Cross

Step 3: adding required libraries into project.


Comparing those libraries with libraries from clean JSF 2.0 project (look here) or libraries from JSF 2.0 project with Spring (look here) we have extra libraries here: Hibernate libraries marked green, Spring JPA libraries marked red and some third party libraries marked blue. Those blue libraries are:
  • c3p0 libraries for connection pool
  • log4j library and bridge library from sl4j to log4j - Hibernate by default uses sl4j, but we would like to use log4j
  • JDBC driver for PostgreSQL
Step 4: configuration files - will be continued in next post.

-------------------------------------------
Download source files:
The complete working example of mentioned application which will contain all described issues, will be available in the last (second) article of this serie.

Friday, January 28, 2011

JSF 2 with Spring 3 - protection with Spring Security (part 2 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 2.1.7, Spring Framework 3.1, Spring Security 3.1.0.


Requirements:
  • a working example of JSF 2.0 application with Spring Framework integrated (can be found here)
You will learn:
  • how to use Spring Security Framework in order to protect web application
From the previous post we know what Spring Framework is, and what advantages it gives us when used in web application. Business logic managed by Spring is not the only one advantage coming from Spring - we can use Spring's embedded mechanisms to secure our web application. This post will show the basic usage of Spring Security for securing our sample JSF 2.0 webapp. 
What parts of our application will be protected? Consider those scenarios:
1. Only registered user (or page administrator) can see details of a selected bike.
2. Only page administrator can add a new bike to the shop offer.

We need two user roles which will determine the privilleges which user has: registered users role and admin users role. Moreover, for the scenario 2, we have to add a new function: adding new bike. For this function we will create a page addBike.xhtml and a JSF managed bean for that page, named addBike.java.

addBike.xhtml source code is shown below:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
  <ui:composition template="../shopTemplate.xhtml">
       
        <ui:define name="content">
        <h:form>
         <h:outputText value="#{msg['bikes.list.name']}: "/><h:inputText value="#{addBike.name}" /><br/>
         <h:outputText value="#{msg['bikes.list.price']}: "/><h:inputText value="#{addBike.price}" /><br/>
         <h:outputText value="#{msg['bikes.list.discountprice']}: "/><h:inputText value="#{addBike.discountPrice}" /><br/>         
         <h:outputText value="#{msg['bikes.list.description']}: "/><h:inputText value="#{addBike.description}" /><br/>
         <h:commandButton action="#{addBike.addNewBike}" value="#{msg['bikes.add.button']}" />
        </h:form>
        </ui:define>

  </ui:composition>
</html>
Nothing special - standard form for entering the data.
addBike.java source code is also simple:
package com.jsfsample.managedbeans;
...
@ManagedBean(name="addBike")
@SessionScoped
public class AddBike implements Serializable {

 private static final long serialVersionUID = -2155913853431899821L;
 
 
 @ManagedProperty("#{bikeDataProvider}")
 private BikeDataProvider bikeDataProvider; // injected Spring defined service for bikes
 
 private String name;
 private String description;
 private String price;
 private String discountPrice;
 private Integer categoryId;
 
 public String addNewBike(){

  Bike newBike = new Bike();
  newBike.setName(getName());
  newBike.setDescription(getDescription());
  newBike.setPrice(Integer.parseInt(getPrice()));
  newBike.setDiscountPrice(Integer.parseInt(getDiscountPrice()));
  newBike.setCategory(categoryId);
  
  // save new bike and return to the shop
  bikeDataProvider.add(newBike);  
  return "/bikesShop.xhtml";
 }; 
 ...
}
Please note that we use here BikeDataProvider.java class, which is Spring managed service, the same we used for loading bikes list and loading a certain bike details in previous post.

Now it is time for protected parts of application. I will show two ways of protecting webapp: protecting resources (like access to certain page) and protecting business logic methods execution. Scenario 1 will be an example of protecting business logic and scenario 2 will be an example of protecting resources.
When user tries to access the protected area (resource or invoke protected method), application will check user roles and based on them will decide if let the user go further or force him to log in. Log in - that's right - a login page will be displayed where user will enter his credentials. Based on them Spring Security will decide what roles user has and depends on assigned roles further action will be continued or not. Let's modify our application to use Spring Security:

Step 1. Modify configuration files:
applicationContext.xml source:
...
 <!-- 
 resource security  
 -->
 <sec:http auto-config="true" access-denied-page="/faces/accessDenied.xhtml">
  <sec:form-login login-page="/faces/login.xhtml" />
  <sec:intercept-url pattern="/faces/admin/**" access="ROLE_ADMIN" />     
 </sec:http>
 <!-- 
 business logic (method) security 
 -->
 <sec:global-method-security
  secured-annotations="enabled" jsr250-annotations="enabled" >  
 </sec:global-method-security>
 <!-- 
 manager responsible for loading user account with assigned roles 
 -->
 <sec:authentication-manager alias="authenticationManager">
  <sec:authentication-provider
   user-service-ref="userDetailsService" />
 </sec:authentication-manager>
 ...
Access-denied-page is invoked when user is authenticated but is not authorized to access protected resources. When user is not authenticated, he is moved into form-login instead of access-denied-page.
web.xml source:
...
 <filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 ...
Step 2. Additional pages: login.xhtml and accessDenied.xhtml.
accessDenied.xhtml is simple page displaying only a message saying that the user is authenticated but still is not authorized to go further.
login.xhtml is a simple page with login form where user enters his credentials (login and password). The more interesting part is corresponding managed bean LoginBean.java which uses a Spring service for authenticating users:
package com.jsfsample.managedbeans;
...
@ManagedBean(name = "loginBean")
@SessionScoped
public class LoginBean implements Serializable {
 private static final long serialVersionUID = 1L;

 private String login;
 private String password;

 @ManagedProperty(value = "#{authenticationService}")
 private AuthenticationService authenticationService; // injected Spring defined service for bikes


 public String login() {

  boolean success = authenticationService.login(login, password);
  
  if (success){
   return "bikesShop.xhtml"; // return to application but being logged now 
  }
  else{
   FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Login or password incorrect."));   
   return "login.xhtml";
  }
 }
 ...
}
When login was successful and user is authenticated, he is moved to the shop. If not a proper message is displayed and user can re-enter his credentials or go back to the shop without login. Let's look inside AuthenticationService.java class which is a service deciding if user is authenticated or not.

Step 3. AuthenticationService implementation:
package com.jsfsample.application.impl;
...
@Service("authenticationService")
public class AuthenticationServiceImpl implements com.jsfsample.application.AuthenticationService {


 @Resource(name = "authenticationManager")
 private AuthenticationManager authenticationManager; // specific for Spring Security

 @Override
 public boolean login(String username, String password) {
  try {
   Authentication authenticate = authenticationManager
     .authenticate(new UsernamePasswordAuthenticationToken(
       username, password));
   if (authenticate.isAuthenticated()) {
    SecurityContextHolder.getContext().setAuthentication(
      authenticate);    
    return true;
   }
  } catch (AuthenticationException e) {   
  }
  return false;
 }
 ...
}
This Spring managed service uses internally a class AuthenticationManager, which comes from Spring Security and was defined as a manager in applicationContext.xml file:
...
 <!-- 
 manager responsible for loading user account with assigned roles 
 -->
 <sec:authentication-manager alias="authenticationManager">
  <sec:authentication-provider
   user-service-ref="userDetailsService" />
 </sec:authentication-manager>
 ...
Note that we do not explicit define AuthenticationManager! It is a ready to use object. But AuthenticationManager has helper service named userDetailService defined in applicationContext.xml file - this service must be written by our own.

Step 4. Implementation of userDetailService
userDetailsService source code is shown below:
package com.jsfsample.application.impl;
...
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

 private HashMap users = new HashMap();
 
 @Override
 public UserDetails loadUserByUsername(String username)
   throws UsernameNotFoundException{
  
  org.springframework.security.core.userdetails.User user = users.get(username);
  
  if (user == null) {
   throw new UsernameNotFoundException("UserAccount for name \""
     + username + "\" not found.");
  }
  
  return user;
 }

 @PostConstruct
 public void init() {
  
  // sample roles  
  Collection adminAuthorities = new ArrayList();
  adminAuthorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
  
  Collection userAuthorities = new ArrayList();
  userAuthorities.add(new GrantedAuthorityImpl("ROLE_REGISTERED"));
  
  boolean enabled = true;
  boolean accountNonExpired = true;
  boolean credentialsNonExpired = true;
  boolean accountNonLocked = true;
  
  // sample users with roles set
  users.put("admin", new org.springframework.security.core.userdetails.User("admin", "admin", enabled, accountNonExpired,
    credentialsNonExpired, accountNonLocked, adminAuthorities));
  
  users.put("user", new org.springframework.security.core.userdetails.User("user", "user", enabled, accountNonExpired,
    credentialsNonExpired, accountNonLocked, userAuthorities));
 }
}
We have here a Spring Security specific objects representing users and roles. In the init() method I created some mocked data two roles representing page administrators and registered users - ROLE_ADMIN and ROLE_REGISTERED. For each role I created a single account: admin (password: admin) for the ROLE_ADMIN and user (password: user) for the ROLE_REGISTERED. That's all - it is time to protect applicartion.

Step 5. Protecting application.
5 a) Scenario 1: protecting business logic. We have to protect invoking a method which allows to see bike details. This method is placed inside BikeDataProvider.java service class. In order to protect the method we have to add an annotation defining roles allowed to execute this method:
package com.jsfsample.services;
...
public interface BikeDataProvider {
 ...
 
 @RolesAllowed({"ROLE_ADMIN","ROLE_REGISTERED"}) 
 public abstract Bike getBikeById(Integer id);
 
 public abstract void add(Bike newBike);
}
This simply means that only registered users or admin users can see bike details. 
Why we do not protect the add(...) method? Because we protect the whole page access where this method is executed - of course in addition we can also protect this method by annotating it with @RolesAllowed({"ROLE_ADMIN"}).
5 b) Scenario 2: protecting resource. According to rules of protecting resources defined in applicationContext.xml, we protect all resources which are located inside /admin directory. So we have to create a directory /admin under /WebContent directory and move addBike.xhtml page there. It should look like this:




Note: there is a little trick in the protecting resources like pages in JSF. Spring Security tries to match exact URL address to apply the rule. But in JSF there is a "old URL" issue - after navigtation from page A to page B, URL address in browser still points to page A. In order to make the rule working we have to force the browser to show the current URL instead of old one. It is done by adding a special command into the navigation string returning a page for adding a bike:
public String showForm(){  
 ...  
 return "/admin/addBike.xhtml?faces-redirect=true";
}


That's all about Spring Security in our sample application. 
How to test it? After deploying application on the server and starting the server, we have to open a browser and type in URL:

http://localhost:8080/JSF2FeaturesSpring

Then try to display some bike details. When promped for login, enter credentials: user, user and try again. Then try to add a new bike - You should see access denied page. The close the application and clean the browser cache and try the same with the user admin, admin.

-------------------------------------------
Download source files:

Note: make sure that Java, Eclipse and Tomcat are properly installed and configured for running the project (additional configuration may be required if different directories are used).

Eclipse complete sample project is here (with all required libraries). The sample project is a ready to run application which contains all described Spring Security issues in this post. You can also download a war file located here (just copy it inside webapps folder in Your Tomcat and start Tomcat with the script startup.bat)

Tuesday, December 14, 2010

JSF 2 with Spring 3 - basics (part 1 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 2.1.7, Spring Framework 3.1.1, Spring Security 3.1.0.

Requirements:
  • a working example from the last article of a serie introducing new JSF 2.0 features.
You will learn:
  • how to integrate Spring Framework into JSF 2.0 application
In the previous three posts I described some interesting JSF 2.0 features and I put them together in the sample application. Those parts were mostly focused on web content, a GUI and its behaviour.
What about the server side? What about the business logic executed underneath? Do we had a business logic in the sample application mentioned above? Of course we had. Presenting bikes list or a certain bike under some condition -  this is business logic resposniblity. Filtering bikes and presenting only those with the discount - this is also business logic. Don't think of it as a naive filtering of presented data - the business logic decides what does it mean that the certain bike has discount - it can be lower price but it can be also more complicated. In the previous example we had a class named BikeDataProvider.java which represented business logic. It was a singleton invoked with the help of static method getInstance() anywhere where needed.
When the application starts to grow up, we have more business logic accomplishing some business cases. We need something that will help us to manage the whole business logic in an elegant way - this is where Spring comes to play.
We will change the BikeDataProvider class into object created and managed by Spring. This object will be called service. A service which serves business logic. Then the service will be used by JSF managed beans. Let's add Spring to our sample web apllication. 

Step 1: adding required Spring libraries into the project. 


Step 2: creating Spring's configuration file named applicationContext.xml. The file has to be located inside /WEB-INF directory. This is full content of that file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:faces="http://www.springframework.org/schema/faces"
 xmlns:int-security="http://www.springframework.org/schema/integration/security"
 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:sec="http://www.springframework.org/schema/security"
 xsi:schemaLocation="http://www.springframework.org/schema/integration/security http://www.springframework.org/schema/integration/security/spring-integration-security-3.1.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
  http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
  http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-3.1.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 <context:component-scan base-package="com.jsfsample" />

</beans>

Step 3: modifying web.xml by registering listener resposnible for loading Spring in web application.
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
Step 4: modifying faces-config.xml file for allow JSF components use Spring components.
<application>
... <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
...
 </application>
Step 5: modifying BikeDataProvider.java toward Spring managed service.

First of all we will add a new functionality to the application - possibility to add a new bike to the selected category. We need to create an .xhtml page with the form, then managed bean for that page and at the end a business logic method in class BikeDataProvider.java responsible for adding new bike to bikes' list. That's easy part - it will be visible in the attached complete example. 
Assuming that we have this new funcitonality, we can modify .java files for Spring integration. First we create an interface: 
package com.jsfsample.services;
//imports
public interface BikeDataProvider {

 public List<Bike> getBikesByCategory(Integer categoryId,
   boolean onlyWithDiscount);

 public Bike getBikeById(Integer id);

 public void add(Bike newBike); // new function

} 
Then we have to create an implementation named BikeDataProviderImpl.java (yes, I know that this naming convention is bad) which will have the source code from previous BikeDataProvider.java class. This implementation will have Spring specific annotation defining the service:
package com.jsfsample.services.impl;
//imports
@Service("bikeDataProvider")
public class BikeDataProviderImpl implements BikeDataProvider {

 private List<Bike> bikes;
 private Integer currentBikeId;
 
 @PostConstruct
 private void prepareData(){
  bikes = new ArrayList<Bike>();
  
  // MTB
  Bike mtb1 = new Bike();
  mtb1.setId(1);
  mtb1.setName("Kellys Mobster");
  mtb1.setDescription("Kellys Mobster, lorem ipsut...");
  mtb1.setPrice(6500);
  mtb1.setCategory(1); 
  bikes.add(mtb1);
  // other bikes are mocked up the same way
  
 }
 
 public List<Bike> getBikesByCategory(Integer categoryId, boolean onlyWithDiscount) {
  // implementation 
 }
 public Bike getBikeById(Integer id){
  // implementation 
 }

 public void add(Bike newBike) {
  bikes.add(newBike);
 }
} 
The annotation @Service("bikeDataProvider") means that this is Spring managed object (created by Spring) and is visible in the Spring context under the name "bikeDataProvider". @PostConstruct is a little trick here - when object of this class is instantiated by Spring, the method is invoked right after the object is created. I used this for preparing demo data of bikes. The whole BikeDataProviderImpl.java class acts as a simple data source for the application - in the future we will use a real database instead.

Step 6: modifying JSF managed beans to use Spring service inside.

We will use registered Spring service inside JSF managed-beans. For example consider BikeDetails.java managed bean. Previously we loaded certain bike in this way:
package com.jsfsample.managedbeans;
// imports
@ManagedBean(name="bikeDetails")
@RequestScoped
public class BikeDetails {

 private Integer bikeId;
 private Bike bike; 
 
 public void loadBike(){
  bike = BikeDataProvider.getInstance().getBikeById(bikeId);
 }
        ...
}
Now BikeDataProvider.java is not a singleton - it is a Spring service. BikeDetails.java managed bean is changed:
package com.jsfsample.managedbeans;
// imports
@ManagedBean(name="bikeDetails")
@RequestScoped
public class BikeDetails {

 private Integer bikeId;
 private Bike bike; 
 
 @ManagedProperty("#{bikeDataProvider}")
 private BikeDataProvider bikeDataProvider; // injected Spring service

 public void loadBike(){
  bike = bikeDataProvider.getBikeById(bikeId);
 }
        ...
}
We used the name of registered service ("bikeDataProvider") to inject it into JSF managed bean (please note that we used here an interface as an instance variable, Spring injects its concrete implementation). This injection is possible thanks to modifications from step 4.


That's all. Other JSF managed beans responsible for displaying bikes' lists or adding a bike use mentioned Spring service in the same way.

-------------------------------------------
Download source files:
The complete working example of mentioned application which will contain all described issues, will be available in the last (second) article of this serie.