SpringSource has published release candidate 2 of the upcoming 3.0 release of their Spring Framework. New Feature is the compliance with JSR-330 (“Dependency Injection for Java”). The JSR was developed together by Google (for their Guice Framework and SpringSource (for their Spring Framework) and is finally approved since 14.10.2009.
A little example shows how to develop services with interfaces and implementations without dependencies to Spring Framework or Google Guice:
The Maven pom.xml
4.0.0 de.schaeftlein.dev jsr330-sample jar jsr330-sample 0.0.1-SNAPSHOT Sample App with Spring 3.0 RC 2 and JSR330 3.0.0.RC2 org.springframework spring-core ${springVersion} org.springframework spring-beans ${springVersion} org.springframework spring-context ${springVersion} org.springframework spring-asm ${springVersion} org.springframework spring-expression ${springVersion} junit junit 4.7 test javax.inject javax.inject 1 jsr330-sample src/main/java ${basedir}/src/test/java src/main/resources **/.svn **/.svn/** **/_svn _svn **/_svn/** src/test/resources **/.svn **/.svn/** **/_svn _svn **/_svn/** org.apache.maven.plugins maven-compiler-plugin 1.6 org.apache.maven.plugins maven-eclipse-plugin true true _svn .svn org.apache.maven.plugins maven-jar-plugin true org.apache.maven.plugins maven-source-plugin attach-sources verify jar
a simple encode/decode interface
package de.schaeftlein.dev.spring; public interface Encryption { String encode(String value); String decode(String value); }
a simple implementation for Encryption
package de.schaeftlein.dev.spring; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import javax.inject.Named; @Named // service name is the name of the class public class URLEncoderEncyrption implements Encryption { @Override public String decode(String value) { try { return URLDecoder.decode(value, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; // never happen } } @Override public String encode(String value) { try { return URLEncoder.encode(value, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; // never happen } } }
a more secure implementation for Encryption
package de.schaeftlein.dev.spring; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.inject.Named; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import com.sun.org.apache.xml.internal.security.utils.Base64; @Named("secure") // named service bean public class Base64Encyption implements Encryption { private sun.misc.BASE64Encoder base64encoder; private SecretKey key; public Base64Encyption() { try { DESKeySpec keySpec = new DESKeySpec("Your secret Key phrase".getBytes("UTF8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); key = keyFactory.generateSecret(keySpec); base64encoder = new BASE64Encoder(); } catch (Exception e) { e.printStackTrace(); } } @Override public String decode(String input) { try { Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe cipher.init(Cipher.DECRYPT_MODE, key); byte[] bOut = cipher.doFinal(Base64.decode(input.getBytes("UTF-8"))); return new String(bOut, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public String encode(String plainTextPassword) { try { byte[] cleartext = plainTextPassword.getBytes("UTF8"); Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe cipher.init(Cipher.ENCRYPT_MODE, key); return base64encoder.encode(cipher.doFinal(cleartext)); } catch (Exception e) { e.printStackTrace(); } return null; } }
a small interface for a service
package de.schaeftlein.dev.spring; public interface SecureUtil { void compareEncryption(String input); }
a implementation for our service
package de.schaeftlein.dev.spring; import javax.inject.Inject; import javax.inject.Named; @Named("SecureUtil") public class SecureUtilImpl implements SecureUtil { @Inject // automatically set by DI framework @Named("secure") // get the namend bean private Encryption secureEncryption; @Inject // automatically set by DI framework @Named("URLEncoderEncyrption") // get the bean by its classname private Encryption unsecureEncryption; public void compareEncryption(String input){ String encodedSecure = secureEncryption.encode(input); System.out.println("Secure encoded: "+encodedSecure); String encodeUnsecure = unsecureEncryption.encode(input); System.out.println("Unsecure encoded: "+encodeUnsecure); System.out.println("Secure decoded: "+secureEncryption.decode(encodedSecure)); System.out.println("Unsecure decoded: "+unsecureEncryption.decode(encodeUnsecure)); } }
finally a main class for testing
package de.schaeftlein.dev.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { /** * main method */ public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(Main.class.getPackage().getName()); // new way to get Application context without applicationContext.xml available SecureUtil util = ctx.getBean("SecureUtil", SecureUtil.class); // get bean with new generics method util.compareEncryption("an sample input string 1234567890"); } }
output of our Main class
19.11.2009 18:56:03 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@c1b531: startup date [Thu Nov 19 18:56:03 CET 2009]; root of context hierarchy 19.11.2009 18:56:03 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessorINFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 19.11.2009 18:56:03 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@a83b8a: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,secure,SecureUtil,URLEncoderEncyrption]; root of factory hierarchy Secure encoded: QDQvd4uK14YNUQ4uoqhqsZEMDDxUqJAMyisvZr2wsA2GyMC5tSEIiw== Unsecure encoded: an+sample+input+string+1234567890 Secure decoded: an sample input string 1234567890 Unsecure decoded: an sample input string 1234567890