Tuesday, May 14, 2013

Invoking EJB3 in WebSphere using Spring


 Here are the steps to call a method of an EJB (v3.0) deployed in WebSphere 7 from a plain old Java client, either using Spring to shield your code from unnecessary implementation details, or bare-bones straightforward coding style.

Note: Tested against WAS 7 only.

Common Steps

1. Firstly, the Remote interface class is needed and will be referenced in your client code to call the EJB method. Copy the class file or Java source to your Java client workspace. In my example, the remote interface class is org.gizmo.minyakangin.CapKapakRemote
2. If you have a local development WebSphere 7, run the following command to create the stub class

[Class_Folder_Path]:>[WAS_HOME]\AppServer\bin\createEJBStubs.bat org.gizmo.minyakangin.CapKapakRemote -cp .

You should see an output similar to the one below:

Processing the org.gizmo.minyakangin.CapKapakRemote input file.
Command Successful

A file with the name _CapKapakRemote_Stub.class will be created under folder [Class_Folder_Path]\org\gizmo\minyakangin.

3. A missing stub file may produce the following errors when getting a reference to the EJB:

java.lang.ClassCastException: Unable to load class: org.gizmo.minyakangin._CapKapakRemote_Stub

java.lang.ClassCastException: org.omg.stub.java.rmi._Remote_Stub incompatible with org.gizmo.minyakangin.CapKapakRemote

4. At the WebSphere Admin Console, locate the EJB application and ensure a proper JNDI reference is assigned e.g. ejb/CapKapak. It is best not to rely on the default JNDI reference. But if you insist, the default is the fully qualified remote class name i.e. org.gizmo.minyakangin.CapKapakRemote.



5. Also, check the bootstrap port of the application server instance hosting the EJB (my environment is 9812):



6. At your Java client workspace, ensure that com.ibm.ws.webservices.thinclient_7.0.0.jar (under [WAS_HOME]\AppServer\runtimes) and com.ibm.ws.runtime.jar (under [WAS_HOME]\AppServer\plugins) are included in the classpath. Not sure why including only com.ibm.ws.ejb.thinclient_7.0.0.jar doesn't work in my case.

Caveat: The steps only work using IBM JDK (v7). You may need to do some 'hacking' to get it working under a different JVM.


Using Spring 3.x

You can interface with a plain Java interface (no EJB classes or annotations needed) using Spring. Here's the interface:

package org.gizmo.minyakangin;

public interface CapKapak {
	public String getBrand();
}


An EJB3 'bean' can be easily constructed using a JNDI object factory bean, and it's even easier to just use the 'jee' namespace, as below:




	
		
			java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory
			java.naming.provider.url=corbaloc:iiop:localhost:9812
		
	





Note: The 'java.naming.provider.url' value should refer to the WebSphere server's bootstrap address as shown above.

Then in the code (using Spring's JUnit class):

package org.gizmo.minyakangin;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
		"classpath:org/minyakangin/spring-context.xml"})
public class EjbTests extends AbstractJUnit4SpringContextTests {

	CapKapakRemote capKapak;
	
	@Before
	public void before() {
		capKapak = (CapKapakRemote)applicationContext.getBean("capKapak");
	}
	
	@Test
	public void testLoginManager() throws Exception {
		String brand = capKapak.getBrand();
		System.out.println(brand);
	}
}


Using plain Java


package org.gizmo.minyakangin;

import java.util.Properties;

import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

import com.cv.ibs.user.session.LoginManagerRemote;
import com.cv.ibs.utils.SessionUser;

public class StandaloneEjbClient {

	public static void main (String args[]) throws Exception {
		Properties props = new Properties();
		props.put("java.naming.factory.initial", "com.ibm.websphere.naming.WsnInitialContextFactory");
		props.put("java.naming.provider.url", "corbaloc:iiop:localhost:9812");

		InitialContext ctx = new InitialContext(props);
		
		Object ejbBusIntf = ctx.lookup("ejb/CapKapak");
		CapKapakRemote loginManager = (CapKapakRemote)PortableRemoteObject.narrow(ejbBusIntf, CapKapakRemote.class);
		String brand = capKapak.getBrand();
		System.out.println(brand);
	}
}





Tuesday, April 16, 2013

Strategy Pattern Applied - KeyStoreTemplate

Update: I wrongly attributed the design pattern implementation below to the Template pattern, it's actually the Strategy pattern as pointed out by a user in Reddit. However, the article below is kept in its original form, with just the title changed. Sorry for the confusion :)

The Template design pattern is useful if you have methods that follow a similar pattern but differ only in a few places. Usually, the 'generic' method will call one or several abstract methods, which are then implemented in a concrete class.

The JdbcTemplate of the Spring Framework was (and still is) a life saver. No more unclosed Connection objects that may leak to JDBC connection leaks. No more try/catch blocks that obscure the code logic. Converting the JDBC DAOs of legacy systems to use JdbcTemplate objects provided immediate benefits in terms of simplicity (eliminating copy-and-paste codes) and robust resource management (e.g. closing Connections, ResultSets, Statements).

There are a lot of useful articles detailing what, why and how of this design pattern, so I will not rehash them here. I will just document down how I applied this pattern to solve some age-old problem.

I decided to follow the JdbcTemplate's design style to come up with a KeyStoreTemplate, a class that handles importing or exporting of keys to/from a keystore. To make things simple, this class will only handle 2 things: Importing a key, and exporting a key.

Firstly, the KeyStoreTemplate code (abridged for simplicity):

import org.apache.commons.io.IOUtils;

public class KeyStoreTemplate {

 /**
 * Just enough parameters to open a keystore.
 */
 public KeyStoreTemplate(File keyStoreFile, Provider provider, String keyStoreType, String keyStorePassword) {
  this.keyStoreFile = keyStoreFile;
  this.provider = provider;
  this.keyStoreType = keyStoreType;
  this.keyStorePassword = keyStorePassword;
 }

 /**
 * This is to get/export a key from the keystore.
 */
 public Key getFromKeyStore(KeyStoreExporter exporter) {
  FileInputStream fis = null;
  try {
   KeyStore ks = KeyStore.getInstance(keyStoreType, provider);
         fis = new FileInputStream(keyStoreFile);

         //Keystore file must exists!
         if(keyStoreFile.exists()) {
          ks.load(fis, keyStorePassword.toCharArray());
         } else {
          throw new RuntimeException("Keystore file cannot be located!");
         }
         
         String keyPass = keyStorePassword;

         return exporter.exportKey(ks, keyPass);
         
  } catch (Exception e) {
   throw new RuntimeException("Something went wrong!", e);
  } finally {
   IOUtils.closeQuietly(fis);
  }  
 }

 /**
 * This is to save/import a key to the keystore.
 */
 public void saveToKeyStore(KeyStoreImporter importer) {
  
  FileInputStream fis = null;
  FileOutputStream fos = null;
  try {
   KeyStore ks = KeyStore.getInstance(keyStoreType, provider);
         fis = new FileInputStream(keyStoreFile);

         //Keystore file must exists!
         if(keyStoreFile.exists()) {
          ks.load(fis, keyStorePassword.toCharArray());
         } else {
          throw new BusinessException("Keystore file cannot be located!");
         }
         
         String keyPass = keyStorePassword;

         importer.importPrivateKey(ks, keyPass);
         
         fos = new FileOutputStream(keyStoreFile);
         ks.store(fos, keyStorePassword.toCharArray());
         
  } catch (Exception e) {
   throw new RuntimeException("Something went wrong!", e);
  } finally {
   IOUtils.closeQuietly(fis);
   IOUtils.closeQuietly(fos);
  }
 }
 
}

Notice that there are 2 interfaces: KeyStoreExporter and KeyStoreImporter. These interfaces are implemented by the caller class of KeyStoreTemplate to do the 'effective' stuff, without worrying about the KeyStore details. The KeyStore object is passed in, much like the ResultSet object is passed in when using JdbcTemplate.

import java.security.GeneralSecurityException;
import java.security.KeyStore;

public interface KeyStoreImporter {

 public void importPrivateKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException;
}
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;

public interface KeyStoreExporter {

 public Key exportKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException;
}

So, how to use them? Example as below:

//Key generation and key import
KeyPair keyPair = generateRSAKeyPair();
final Certificate[] certs = CryptoUtils.generateCertificate(keyPair);

RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
final RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();

logger.debug("[generateAndStoreRSAKeyPair] pubKey={},privKey={}", publicKey.getClass(), privateKey.getClass());

keyStoreTemplate.saveToKeyStore(new KeyStoreImporter() {
 @Override
 public void importPrivateKey(KeyStore ks, String keyPassword) throws KeyStoreException {
  ks.setKeyEntry(alias, privateKey, keyPassword.toCharArray(), certs);
 }
});
//Method to get an RSA public key
public RSAPublicKey getRSAPublicKey(final String alias) throws BusinessException {

 return (RSAPublicKey)keyStoreTemplate.getFromKeyStore(new KeyStoreExporter() {
  @Override
  public Key exportKey(KeyStore keyStore, @SuppressWarnings("unused") String keyPassword) throws GeneralSecurityException {
   Certificate cert = keyStore.getCertificate(alias);
   RSAPublicKey publicKey = (RSAPublicKey)cert.getPublicKey();
   return publicKey;
  }
 });
}
//Method to get a secret key
public SecretKey getSecretKey(final String alias) throws BusinessException {

 return (SecretKey)keyStoreTemplate.getFromKeyStore(new KeyStoreExporter() {
  @Override
  public Key exportKey(KeyStore keyStore, String keyPassword) throws GeneralSecurityException {
   SecretKey secretKey = (SecretKey)keyStore.getKey(alias, keyPassword.toCharArray());
   return secretKey;
  }
 });
}

Thursday, March 14, 2013

Cryptography Using JCA - Services In Providers


The Java Cryptography Architecture (JCA) is an extensible framework that enables you to use perform cryptographic operations. JCA also promotes implementation independence (program should not care about who's providing the cryptographic service) and implementation interoperability (program should not be tied to a specific provider of a particular cryptographic service).

JCA allows numerous cryptographic services e.g. ciphers, key generators, message digests to be bundled up in a java.security.Provider class, and registered declaratively in a special file (java.security) or programmatically via the java.security.Security class (method 'addProvider').

Although JCA is a standard, different JDKs implement JCA differently. Between Sun/Oracle and IBM JDKs, the IBM JDK is sort of more 'orderly' than Oracle's. For instance, IBM's uber provider (com.ibm.crypto.provider.IBMJCE) implements the following keystore formats: JCEKS, PKCS12KS (PKCS12), JKS. Oracle JDK 'spreads' the keystore format implementations into the following providers:

  • sun.security.provider.Sun - JKS
  • com.sun.crypto.provider.SunJCE - JCEKS
  • com.sun.net.ssl.internal.ssl.Provider - PKCS12
Despite the popular recommendation to write applications that do not point to a specific Provider class, there are some use cases that require an application/program to know exactly what services a Provider class is offering. This requirement becomes more prevalent when supporting multiple application servers that may be tightly coupled with a particular JDK e.g. WebSphere bundled with IBM JDK. I usually use Tomcat+Oracle JDK for development (more lightweight, faster), but my testing/production setup is WebSphere+IBM JDK. To further complicate matters, my project needs the use of a hardware security module (HSM) which uses the JCA API via the provider class com.ncipher.provider.km.nCipherKM. So, when I am at home (without access to the HSM), I would want to continue writing code but at least get the codes tested on a JDK provider. I can then switch to use the nCipherKM provider for another round of unit testing before committing the code to source control.

The usual assumption is that one Provider class is enough e.g. IBMJCE for IBM JDKs, SunJCE for Oracle JDKs. So the usual solution is to implement a class that specifies one provider, using reflection to avoid compile errors due to "Class Not Found":

//For nShield HSM
Class c = Class.forName("com.ncipher.provider.km.nCipherKM");
Provider provider = (Provider)c.newInstance();

//For Oracle JDK
Class c = Class.forName("com.sun.crypto.provider.SunJCE");
Provider provider = (Provider)c.newInstance();

//For IBM JDK
Class c = Class.forName("com.ibm.crypto.provider.IBMJCE");
Provider provider = (Provider)c.newInstance();


This design was OK, until I encountered a NoSuchAlgorithmException error running some unit test cases on Oracle JDK. And the algorithm I was using is RSA, a common algorithm! How can this be, the documentation says that RSA is supported! The same test cases worked fine on IBM JDK.

Upon further investigation, I realised that much to my dismay, the SunJCE provider does not have an implementation for the KeyPairGenerator service for RSA. An implementation however is found in the provider class sun.security.rsa.SunRsaSign. So the assumption of "1 provider to provide them all" is broken. But thanks to JCA's open API, a Provider object can be passed in when requesting for a Service instance e.g.

KeyGenerator kgen = KeyGenerator.getInstance("AES", provider);

To help with my inspection of the various Provider objects, I've furnished a JUnit test to pretty-print out the various services of each registered Provider instance in a JDK.

package org.gizmo.jca;

import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.crypto.KeyGenerator;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;

public class CryptoTests {

 @Test
 public void testBouncyCastleProvider() throws Exception {
  Provider p = new BouncyCastleProvider();
  String info = p.getInfo();
  System.out.println(p.getClass() + " - " + info);
  printServices(p);
 }
 
 @Test
 public void testProviders() throws Exception {
  
  Provider[] providers = Security.getProviders();
  for(Provider p : providers) {
   String info = p.getInfo();
   System.out.println(p.getClass() + " - " + info);
   printServices(p);
  }
 }
 
 private void printServices(Provider p) {
  SortedSet services = new TreeSet(new ProviderServiceComparator());
  services.addAll(p.getServices());
  
  for(Service service : services) {
   String algo = service.getAlgorithm();
   System.out.println("==> Service: " + service.getType() + " - " + algo);
  }
 }

 /**
  * This is to sort the various Services to make it easier on the eyes...
  */
 private class ProviderServiceComparator implements Comparator {

  @Override
  public int compare(Service object1, Service object2) {
   String s1 = object1.getType() + object1.getAlgorithm();
   String s2 = object2.getType() + object2.getAlgorithm();;

   return s1.compareTo(s2);
  }

 }
}

Anyway, if the algorithms you use are common and strong enough for your needs, the BouncyCastle provider can be used. It works well across JDKs (tested against IBM & Oracle). BouncyCastle does not support JKS or JCEKS keystore formats, but if you are not fussy, the BC keystore format works just fine. BouncyCastle is also open source and can be freely included in your applications.

Tip: JKS keystores cannot store SecretKeys. You can try it as your homework :)

Hope this post will enlighten you to explore JCA further, or at least be aware of the pitfalls of 'blissful ignorance' when working with JCA.

Tuesday, January 22, 2013

Beginning HP-UX for Linux Junkies


I've got the (unfortunate) privilege of doing some tinkering using a HP-UX box. But, as any battle-hardened Linux user would tell you, HP-UX (along with AIX, Solaris and other Unixes) is a different animal. Things may look similar, but lots of commands for simple things are different in parameters and usage. Here's what I learnt during this short stint using HP-UX and hopefully this will be good start for beginners.

Before you proceed

Ensure that the IP address of the HP-UX box in /etc/host file is correct. A simple line like this (10.10.10.10 is an invalid address) will cause a lot of headaches:

#commented as 'evidence'
#10.10.10.10    TEST01

Find out machine architecture:

Run: machinfo

Sample output:

CPU info:
   Intel(R) Itanium 2 9100 series processor (1.59 GHz, 18 MB)
   2 cores, 4 logical processors per socket
   532 MT/s bus, CPU version A1
          Active processor count:
          2 sockets
          4 cores (2 per socket)
          4 logical processors (2 per socket)
          LCPU attribute is disabled

Memory: 16353 MB (15.97 GB)


Firmware info:

   Firmware revision:  04.31
   FP SWA driver revision: 1.18
   IPMI is supported on this system.
   BMC firmware revision: 5.38

Platform info:

   Model:                  "ia64 hp server BL870c"
   Machine ID number:      27f7c389-7d33-11ee-45bb-3c46ec670369
   Machine serial number:  SGH55555RB

OS info:

   Nodename:  TEST01
   Release:   HP-UX B.11.31
   Version:   U (unlimited-user license)
   Machine:   ia64
   ID Number: 0670548873
   vmunix _release_version:
@(#) $Revision: vmunix:    B.11.31_LR FLAVOR=perf


Installing Bash shell

Once you've identified your HP-UX hardware and OS version (mine's ia64 aka Itanium running OS v11.31 aka 11i v3), go to http://hpux.connect.org.uk and search for 'bash'. As of the time of this article, the direct link to the bash download page is http://hpux.connect.org.uk/hppd/hpux/Shells/bash-4.2.039/. The page also shows the run-time dependencies needed. You'll need to download & install the dependencies as well (you can use 'depothelper' to install an application along with its dependencies in one go).

1) Download http://hpux.connect.org.uk/ftp/hpux/Shells/bash-4.2.039/bash-4.2.039-ia64-11.31.depot.gz
2) Transfer file to HP-UX box e.g. /tmp/bash-4.2.039-ia64-11.31.depot.gz
3) Unzip: gunzip /tmp/bash-4.2.039-ia64-11.31.depot.gz
4) Install: swinstall -s /tmp/bash-4.2.039-ia64-11.31.depot bash

By default, all external program executables are installed to /usr/local/bin. So to run: /usr/local/bin/bash

If you see this prompt:

bash-4.2#

Then you have installed bash successfully.

Using X-Windows

HP-UX uses CDE (Common Desktop Environment), so you can use Xming or Cygwin/X and run the following command to bring up the X-Windows login screen:

Xming: Xming -query 129.168.23.22

Cygwin/X: xwin -query 129.168.23.22

There's nothing much to see compared to Linux distros.


Using built-in System Management Homepage web application


By default, HP-UX comes with a nifty web application hosted within its box. This web application is like webmin.

To run: hpsmh autostart

Just point your web browser to https://129.168.23.22:2381/cpqlogin.htm (replace with actual IP of the box).



Useful link: http://www.cyberciti.biz/tips/hp-ux-networking-related-tools-and-commands.html

Wednesday, January 02, 2013

IntelliJ CE for Maven WebApps


IntelliJ Community Edition is a free and good IDE for plain old Java programming, and is also good for Android development. When it comes to enterprise/web development, the Ultimate Edition is the better choice if you can afford it. However, you can also do some simple Java web development using Maven and running your application server outside of IntelliJ. No doubt it's less integrated but you can at least breathe some life exploring more of IntelliJ.

Software used:

  • Oracle JDK 7
  • Maven v3.0.4
  • IntelliJ Community Edition (CE) v12.0.1
  • Apache Tomcat 7


Before starting, ensure that the M2_HOME environment variable has been set to point to your local Maven home folder.

IntelliJ Steps:

  1. Enable on-the-fly compilation. Go to File > Settings > Compiler, check 'Use external build' and 'Make project automatically'.
  2. Ensure the Maven plugin is enabled. Go to File > Settings > Plugins (under IDE Settings), item 'Maven Integration' should be checked. Restart the IDE if needed/prompted.
  3. Create a new project. 
    1. Go to File > New Project..., choose 'Maven Module' (under Java). Set the project location to the desired folder which will house your pom.xml file. Click 'Next' (proceed to create the folder if needed).
    2. Check 'Create from archetype' and select 'maven-archetype-webapp'. Click 'Next'. Click 'Finish'.
  4. At the right side of the IDE, there will be a button for 'Maven Projects'. Click it to bring up the Maven panel. From the panel, you can then run targets e.g. install, clean, package and check the dependencies.
  5. At the right side of the IDE, there will be a button for 'Maven Projects'. Click it to bring up the Maven panel. From the panel, you can then run targets e.g. install, clean, package and check the dependencies.
  6. Point the class files to the web application's WEB-INF/classes folder. Right-click the project root folder, select 'Open Module Settings'. At the 'Paths' tab, under 'Compile output', select/ensure 'Use module compile output path', and change the 'Output Path' to your project's 'src/main/webapp/WEB-INF/classes' folder*.
  7. Add 'maven-dependency-plugin' plugin to copy dependency JARs to WEB-INF/lib folder. Add the following snippet to the pom.xml file (top-level):
    
     
      local
      
       
        
         maven-dependency-plugin
         
          
           install
           
            copy-dependencies
           
           
            ${basedir}/src/main/webapp/WEB-INF/lib
           
          
         
        
       
      
     
    
    
  8. This plugin will instruct Maven to copy all dependency JARs into the 'outputDirectory' path when executing the 'install' task when using profile 'local'. At the Maven panel, check 'local' under Profiles and right-click 'install' under Lifecycles, and select 'Run mavenweb [install]'. After running you should see the junit-3.8.1.jar in the WEB-INF/lib folder.
  9. Add Tomcat webapp config file. This is to specify the Maven webapp folder to be loaded by Tomcat. The simplest:
    
    
  10. Save the contents to the file @ [TOMCAT_HOME]\conf\Catalina\localhost\mavenweb.xml
  11. Run Tomcat. You can use 'catalina start' command under [TOMCAT_HOME]\bin to fire up an instance. Then to test the web app, point your browser to http://127.0.0.1:8080/mavenweb/index.jsp. You should be greeted with a 'Hello World!'.
* I use the 'src' folder so that there's no need to run any Maven 'compile' task and Tomcat can detect a change and reload the webapp. But it's up to personal preference as this way will mean extra care to be taken to cleanup or ignore files for source control check-ins.

Final note
If you need to use a proxy to access the Internet, you can configure Maven to use it by right-clicking the project root folder, select 'Maven' > [Open/Create] settings.xml. Then add the proxy settings e.g.



    
        
            true
            http
            127.0.0.1
            8118
            proxyuser
            somepassword
            www.google.com|*.somewhere.com
        
    

Links:
  • Maven - http://maven.apache.org/download.cgi
  • IntelliJ Community Edition (CE) - http://www.jetbrains.com/idea/
  • http://forum.springsource.org/showthread.php?100694-Maven-dependencies-to-lib-directory
  • http://maven.apache.org/guides/mini/guide-proxies.html

Monday, December 10, 2012

Generating Certificates With BouncyCastle

Usually, after a serious public-private key generation session, the private key would need to be stored. The obvious place would be a key store. The commonly used method to accomplish this using java.security.KeyStore class:

void setKeyEntry(String alias, byte[] key, Certificate[] chain) 

You'll need at least one Certificate object to accompany the private key. You may be tempted (or already attempted) to 'skip' producing the Certificate object using this method:

void setEntry(String alias, KeyStore.Entry entry, KeyStore.ProtectionParameter protParam)

But you'll discover that a java.security.KeyStore.PrivateKeyEntry object needs a Certificate[] object passed in as well.

This led to the code below to generate the required Certificate object, just enough to fulfil the requirements to save the private key:

 @Deprecated
 private Certificate[] generateCertificateOld(KeyPair keyPair) throws Exception {
        Date startDate = new Date(System.currentTimeMillis());
        Date expiryDate = DateUtils.parseDate("01/01/2100", new String[] { "dd/MM/yyyy" });
        BigInteger serialNumber = new BigInteger(String.valueOf(System.currentTimeMillis()));

        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        X500Principal dnName = new X500Principal("CN=Storage Certificate");

        certGen.setSerialNumber(serialNumber);
        certGen.setIssuerDN(dnName);
        certGen.setNotBefore(startDate);
        certGen.setNotAfter(expiryDate);
        certGen.setSubjectDN(dnName); // note: same as issuer
        certGen.setPublicKey(keyPair.getPublic());
        certGen.setSignatureAlgorithm("SHA256withRSA");

        return new Certificate[] {certGen.generate(keyPair.getPrivate())};
 }

Of course, if you have the aid of an IDE, the BouncyCastle methods used are deprecated (using v1.47). So, being a good Java coder, I've followed the advice in the BC javadocs and replaced the deprecated methods with the following equivalent code:

 private Certificate[] generateCertificate(KeyPair keyPair) throws Exception {
  X509v1CertificateBuilder certGen = new JcaX509v1CertificateBuilder(
    new X500Name("CN=Storage Certificate"),
    BigInteger.valueOf(System.currentTimeMillis()),
    new Date(System.currentTimeMillis()),
    DateUtils.parseDate("01/01/2100", new String[] { "dd/MM/yyyy" }),
    new X500Name("CN=Storage Certificate"),
    keyPair.getPublic());

  JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA256withRSA");
  ContentSigner contentSigner = contentSignerBuilder.build(keyPair.getPrivate());
  
  X509CertificateHolder certHolder = certGen.build(contentSigner);

  JcaX509CertificateConverter certConverter = new JcaX509CertificateConverter();
  Certificate cert = certConverter.getCertificate(certHolder);

  Certificate[] certs = { cert };
  return certs;
 }

May your sanity be in check as you navigate through the waters of Java security.

Thursday, November 01, 2012

Late Adopter's Guide To JSF


'The Late Adopter's Guide' is a short composition to help developers who are busy supporting legacy (e.g. JDK 1.4, EJB 2.1, Struts 1.x, JSP) Java technologies (like me!) that they have little time to try out newer stuff or there were technical limitations trying to introduce newer stuff into existing systems. But now you are itching to learn that one technology you've been craving all along.

This post will focus on JSF (Java Server Faces).

JSF isn't a new technology but was saddled with limited functionality in its early iterations. If it were not a part of the Java EE standard, it wouldn't have survived till today. Now at version 2.1, JSF is mature and now's a good time to pick it up.

There were lots of stuff happening since version 1 till 2.1. This guide will allow you to skip the noise and brings you to the goodness of 2.1 without getting bogged down by legacy issues e.g. adding Facelets support to JSF 1.x.

My recommendation of certain APIs over others is based on personal experience, so feel free to try out others if you are compelled to do so.

So, here are the pointers to smooth JSF-ing:

1) Use JSF 2.1 (and above)
Do not use a lower version of JSF. This will save you lots of heartache. If your system does not meet the minimal requirements for JSF 2.1, then it's better to stick with existing frameworks you're currently using (if it gets the job done, why not?).

JSF 2.1 requires Java 1.5 or later, JSP 2.1, JSTL 1.2 and a Java Servlet 2.5 implementation. Tomcat 6 or 7 is recommended.

Use the latest JSF 2.1 with all its new features i.e. Facelets, parameterized methods in EL

2) Use the Mojarra JSF distribution
It's the RI (reference implementation) and stable. You can try Apache MyFaces but the real gem of JSF is not really the framework, but the component libraries.

3) Use Facelets
Forget about JSPs, even though you'll be tempted to leverage on your existing JSP skills and tools e.g. JSTL, taglibs. Facelets are just XHTML pages which is quite similar to JSPs, except that it won't allow you to embed Java code using scriptlet tags (<% %>), and you'll have to learn the new EL (expression language) syntax which is not JSTL but is almost functionally the same. However, if you have JSTL or OGNL background, then EL will be a piece of cake for you.

Facelets also has in-build support for page templating, so there's no need for 3rd-party page templating libraries like SiteMesh.

4) Don't worry about JBoss EL
There was a buzz about JBoss EL, where it lets you pass parameters to a managed bean's methods (Why was it not included in earlier JSF version? I have no idea). These feature has been incorporated into JSF 2.1

5) Manage JSF Managed Beans via Spring
If you are an ardent Spring user, then it's recommended to use Spring to manage JSF's managed beans' dependencies. JSF's dependency injection framework is decent but you'll definitely miss Spring's more powerful and sophisticated features.

Or you can go CDI if you want to go standard Java EE.

6) Use a component library
The best thing about JSF is there are so many component libraries to choose from. RichFaces, OpenFaces, IceFaces, you name it.

But if you want to skip R&D and dive right into the action, I recommend to start with PrimeFaces. But chances are that if you are comfortable with a particular library, you won't be inclined to switch. Caveat emptor?

If you don't want to use a component library, you'll be missing most of the goodness that JSF has to offer.

You can use multiple component libraries in a single web application, but it would be messy and incur unnecessary overhead in memory.

Summary

Well, I hope this abridged guide is a good start for you to look in the right direction in learning JSF. Lots of good tutorials in the wild :)