Acquisition de Sun par Oracle

Pas sûr que Java soit gagnant dans l’histoire. Les incertitudes sur le devenir des produits Java n’est pas fait pour inciter les décideurs à opter pour cette technologie. Quelles sont les futures cibles : SpringSource, Redhat ? Sachant que SpringSource a été largement financé par des VC, à mon avis c’est un bon candidat. Bref, je me mets à la place d’un DSI aujourd’hui; si je ne veux pas prendre de risques j’opte pour .Net et les produits Microsoft : ligne de produits complète, cohérente et intégrée qui ne va pas disparaître d’ici 6 mois (j’exagère un peu…).

Je pense aussi que la période de flottement qui va suivre accentuée en + par une baisse d’investissements liée à la conjoncture va freiner grandement l’innovation autour de la plateforme Java et laisser le champ libre à d’autres technologies. Java n’est pas prêt de combler le retard sur C#.

Bref, sans doute quelques mois difficiles en perspective pour la plateforme Java avant d’y voir + clair.

htmlunit kudos

I have been happily surprised by htmlunit. Actually, for a personal project, rewriting a rails app to Seam I tried to find a replacement of excellent Ruby library hpricot. I needed to perform Xpath expression on a HTML DOM tree to retrieve nodes.Well, htmlunit combined with Neko html parser and jaxen Xpath excels at just doing that. Htmlunit is also used by Canoo web testing .Here’s a code snippet to retrieve all USA states on Yahoo Weather :

final WebClient webClient = new WebClient();
final HtmlPage page = (HtmlPage) webClient.getPage("http://weather.yahoo.com/regional/USXX.html");
HtmlUnitXPath xpath = new HtmlUnitXPath("//div[@class='clearfix' and @id='browse']/ul/li/a");
List nodes = (List)xpath.selectNodes(page);
for (HtmlAnchor anchor: nodes) {
System.out.println(anchor.asText());
}

Ok maybe htmlunit could reduce its dependencies and use Xpath support added to Java 5 (via Jaxp 1.3). But that’s what i like about Java plateform: there’s virtually a library for every need. And with (more or less) recent additions to the language: Generics, autoboxing, enums, DSL like code constructions (Fluent Interfaces) and future additions like closures, there are less and less reasons to use dynamically typed languages (even if i like Groovy).

Create your own @Logger annotation

Some frameworks like Seam use the @Logger annotation to instantiate a logger. Seam discovers at deployment annotated classes (see the Scanner class for instance).You could mimic this behaviour with Spring and its AOP capabilities on Spring beans with the <aop:aspectj-autoproxy/> feature.But if you don’t want to bootstrap your application with an IOC container or a framework, there’s still AspectJ AOP to the rescue.For the example, let’s create the Logger marker annotation (AspectJ requires the target retention to be set to RUNTIME).

@Target({FIELD})
@Retention(RUNTIME)
@Documented
public @interface Logger {}

Now in any class of your application, create a Logger (to make it short we’ll use the commons-logging API and its org.apache.commons.logging.Log interface).Example:

@Logger private org.apache.commons.logging.Log logger;

Then the aspect with Aspectj annotated feature and a bunch of reflection to instantiate the logger appropriately (it only invokes the LogFactory and sets the proper class name).

@Aspect
public class LoggerAspect {
@Before("get(@Logger Log biz.dewavrin..*)")
public void doSomething(JoinPoint thisJoinPoint) {
System.out.println("ASPECT logger applied");
Field[] fields = thisJoinPoint.getTarget().getClass().getFields();
Class clazz = thisJoinPoint.getSignature().getDeclaringType();
try {
Field field = clazz.getDeclaredField(thisJoinPoint.getSignature().getName());
field.setAccessible(true);
if (null == field.get(thisJoinPoint.getTarget()) ) {
field.set(thisJoinPoint.getTarget(), new KeyLogger(thisJoinPoint.getSignature().getDeclaringTypeName()));
}
} catch (Throwable t) {
System.err.println("Warning aspect no applied on class="+thisJoinPoint.getTarget().getClass().getCanonicalName());
}
}
}

The key here is the pointcut definition with a @Before advice and the get pointcut which intercepts accesses to every field annotated with @Logger annotations from a base package and its descendents.To build with maven, bind the maven’s aspectj plugin compile goal to your compile phase:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

Note that the aspect could be packaged in a dedicated library and woven to your classes (see aspects libraries) for usage example.

=> Ok this example is only for demonstrative purpose and adds the overhead of reflection on every access to common’s logging Log implementation getters !So it might not be a good idea after all due to performance penalty. But it’s just a starting point for other annotations with aspects ideas to build your own framework.

Memory leaks

Crazy Bob posted on ThreadLocal memory leaks.This type of memory leak really annoys me because I see it very often on Java EE servers and developers are not aware of it.The error is mostly annoying in development, testing environmentswhere the Java EE server is not restarted and the applicationsare just redeployed. Therefore, threads (of thread pools) are not recreated and hold references to old application classes.

My advice is CLEAN YOUR THREADLOCALs

Add a servlet filter, Web frameworkinterceptor or WS handler to set all ThreadLocal variables to null just beforereturning the response to the client. Lower level solutions should be preferred and turn out to be less risky. A dummy implementation (to give an idea) would be a servlet filter:

public class ContextCleanerFilter implements Filter {
private ContextCleaner ctxCleaner;
public void init(FilterConfig filterConfig) {
// CtxCleaner instantiated directly boooh !!!
ctxCleaner = new StaticContextCleaner();
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Reset ThreadLocals before processing the request
if (ctxCleaner != null) ctxCleaner.cleanAll();
chain.doFilter(request,response);
// Reset ThreadLocals after processing the request
if (ctxCleaner != null) ctxCleaner.cleanAll();
}
public void destroy() {
}
}

with a ContextCleaner Interface:

public interface ContextCleaner {
boolean cleanAll();
}

and a dummy implementation:

public class StaticContextCleaner implements ContextCleaner {
public boolean cleanAll() {
UserSession.setSessionData(null);
return true;
}
}

Where UserSession has static accessors to handle the ThreadLocal and is used by application code to store objects in a ThreadLocal instance:

public class UserSession {
private static ThreadLocal m_session= new ThreadLocal();
public static void setSessionData(SessionData sessionData){
m_session.set(sessionData);
}
public static SessionData getSessionData(){
return (SessionData)m_session.get();
}
}

The problem with this implementation is that it only works with classes that you controland are aware that they use ThreadLocal variables. Maybe with reflection it’s possible to accessthe current Thread’s Map which stores ThreadLocal objects and set them to null one by one. But it would be highly risky if your application server uses ThreadLocal for its own usage.

For further information on ThreadLocal memory leaks see this link