gif animé ordinateur

mercredi 6 novembre 2013

ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method

I am actually working on some web application under Tomcat 6 and SPRING, and try to bind some Spring-Aop aspect to inspect some business events. So i faced some configuration problem and had to google longtime before everything worked correctly.
So i want to share this post with all this may concern
First of all, i used tomcat6 as MAVEN plugin,
Starting my tomcat6 throws the exception bellow :
org.springframework.beans.factory.BeanCreationException : Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar

and the cause is : java.lang.IllegalStateException : ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar


To correct this, just add  to your web module pom.xml the flowing yellow color xml tags :

<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<contextFile>${conf.tomcat}</contextFile>
<path>/myAppPath</path>
<uriEncoding>UTF-8</uriEncoding>
<useTestClasspath>true</useTestClasspath>
<useSeparateTomcatClassLoader>true</useSeparateTomcatClassLoader>
<classLoaderClass>org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader</classLoaderClass>
</configuration>
<dependencies>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument-tomcat</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</plugin>

 Dont forget to add the spring-instrument-tomcat, dependency, otherwise it 'll not work.
This is what Spring authors proposed to you :

Tomcat's default class loader does not support class transformation which is why Spring provides an enhanced implementation that addresses this need. Named TomcatInstrumentableClassLoader, the loader works on Tomcat 5.0 and above and can be registered individually for each web application as follows:
  • Tomcat 6.0.x or higher
    1. Copy org.springframework.instrument.tomcat.jar into $CATALINA_HOME/lib, where $CATALINA_HOME represents the root of the Tomcat installation)
    2. Instruct Tomcat to use the custom class loader (instead of the default) by editing the web application context file:
      <Context path="/myWebApp" docBase="/my/webApp/location">
          <Loader
              loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
      </Context>
      Apache Tomcat 6.0.x (similar to 5.0.x/5.5.x) series supports several context locations:
      • server configuration file - $CATALINA_HOME/conf/server.xml
      • default context configuration - $CATALINA_HOME/conf/context.xml - that affects all deployed web applications
      • per-web application configuration which can be deployed either on the server-side at $CATALINA_HOME/conf/[enginename]/[hostname]/[webapp]-context.xml or embedded inside the web-app archive at META-INF/context.xml
For efficiency, the embedded per-web-app configuration style is recommended because it will impact only applications that use the custom class loader and does not require any changes to the server configuration. See the Tomcat 6.0.x documentation for more details about available context locations. 

This SPRING solution didn't fill your need if you are using TOMCAT as MAVEN plugin.

Now Configure your spring xml context by adding some XML tags

<?xml version="1.0" encoding="UTF-8"?>
beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd"

>

<!-- HERE ADD MORE CONF AND BEAN DECLARATION-->
 

<!--
Activates various annotations to be detected in bean classes: Spring's
@Required and @Autowired, as well as JSR 250's @Resource.
-->
<context:annotation-config />

<aop:aspectj-autoproxy />
<context:load-time-weaver/>
</
beans>.

Now that your Spring is correctly configured, you can create your SPRING AOP Classes, may be by @Aspect, @PointCut  Annotation ...etc.

Hope this 'll help.  

mercredi 11 septembre 2013

Hibernate Criteria, Duplicate Alias and Restrictions

I want to share this snippet with all whom it may concern.It seems important and useful.
During my recent Java developments, I tried to expand dynamically, one Hiernate-criteria object with an unknown in advance restrictions or joins. So before adding any, my program is to verify whether or not this join, its aliase are or not already added, if this is not the case, then it is added.

This is the code snippet :

private String createAliasIfNotAlreadyExist(Criteria criteria,String associationPath, String newAlias) {  CriteriaImpl criteriaImpl = (CriteriaImpl)criteria;  @SuppressWarnings("unchecked")  Iterator<Subcriteria> it = criteriaImpl.iterateSubcriteria();  boolean aliasAlreadyExists = false;  String alias =null;  while(it.hasNext()){      Subcriteria subCriteria = it.next();    if (associationPath.equals(subCriteria.getPath())) {// identifie la jointure sur l'objet     aliasAlreadyExists = true;     alias = subCriteria.getAlias();// l'alias     //System.out.println("associationPath : '" + associationPath+"' already exist with alias = '" + alias+"'");     break;    }  }    if(!aliasAlreadyExists){   //System.out.println("associationPath : '"+associationPath+"' doesn't exists ");   criteria.createAlias(associationPath, newAlias,CriteriaSpecification.LEFT_JOIN);   criteria.setFetchMode(associationPath, FetchMode.JOIN);   alias= newAlias;   //System.out.println("new one is created");    }    return alias; }

private void addRestrictionIfNotAlreadyExists(Criteria criteria, Criterion restriction) { CriteriaImpl criteriaImpl = (CriteriaImpl)criteria;   @SuppressWarnings("unchecked")   Iterator<CriterionEntry> itit = criteriaImpl.iterateExpressionEntries();   boolean expressionAlreadyExist = false;   while (itit.hasNext()) {     CriterionEntry criterionEntry = itit.next();     Criterion cc = criterionEntry.getCriterion();      if(cc.toString().equals(restriction.toString())){      expressionAlreadyExist=true;      break;     }   }   if(!expressionAlreadyExist){   System.out.println("RESTRICTION '"+restriction+"' IS ADDED TO CRITERIA");    criteria.add(restriction);   }else{    System.out.println("CRITERIA ALREADY CONTAINS RESTRICTION : '"+restriction+"'");   } }


dimanche 8 septembre 2013

Kill your application with Hibernate subselect

I'm actually working on some Hibernate criteria developpements. So i usually google to fill some task and get more comprehension of Hibernate criteria concept's.
While doing so, i fortunately found this important atricle, and want to share it with my blog's readers.

First of all, i want to thank the article's author, Mr. Mikalai Alimenkou.

Now, let's all take a look on this :

If you want to kill your application silently the best way is to use Hibernate 'subselect' fetching strategy. Lets discuss the issue in details. Imagine that you have entities 'Post' and 'Comment' in the domain model with corresponding tables in the database:


public class Post {
    private Long id;
    private String title;
    private String body;
    private Set<Comment> comments;
    ...
}

public class Comment {
    private Long id;
    private String text;
    ...
}


Of course you use 'one to many' relationship to map relations between posts and comments (using 'post_id' column from comments table). It doesn't matter what mapping type you prefer (annotations of XML based). All seems good at this moment and you decide to choose 'subselect' fetching strategy for comments collection. You also create a number of unit tests to make sure that you mapping is well done and works fine. Now you want to create method to find last 10 posts for your home page. You decide to use Criteria API for this purpose:

List posts = session.createCriteria(Post.class)
     .addOrder(Order.desc("id"))
     .setMaxResults(10)
     .list();


You again create some unit tests to make sure that method works as expected. But of course you don't review SQL queries in Hibernate logs to check if all is as you expect to be. Hibernate generates following SQL queries for you (example from PostgreSQL database):

select post0_.id as id0_, 
post0_.title as title0_, 
post0_.body as body0_ 
from Post post0_ 
order by
post0_.id desc
limit 10;

select
comment0_.post_id as post5_1_,
comment0_.id as id1_0_,
comment0_.text as text1_0_
from Comment comment0_ 
where comment0_.post_id in (
   select post0_.id 
   from Post post0_
); 


Pay attention to the second query, especially to its subquery part. Limitation is not included in the subquery! What is going on here? It seems that Hibernate is going to load full comments table in memory and then select from them related to top posts selected before. Crazy behavior! Initially, when database is empty or there is low amount of comments, your application will work well. But every time somebody opens your home page with top blogs shown query loads all comments in memory, so you have performance penalty. This penalty is proportional to the number of comments in the database. Once (may be after some monthes of usage in production) you will find that all memory allocated to your application is filled and garbage collector eats 100% of CPU time. Thanks god for profilers, especially for VisualVM. It is hard to believe that such small issue in Hibernate may cause such dramatic effects. There is an opened issue in Hibernate bug tracker, but it has minor priority. We need to keep living with it, so another approach should be applied. The best way to avoid these issues is to use 'batch select' fetching strategy with lazy loading (or without it depending on application needs). Be careful and develop with pleasure!

In my turn, i hope you'll enjoy, and hope this'll serve

dimanche 11 août 2013

Java searching whole word in text

I recently used to face some issues in searching a whole word in given text. So, after googling and testing many regular expression pattern, i finally optimise a java algorithme who full this request.
In addition to find whole word, my algorithme should take in account the fact that my text is iso-latin encoding (french word), thus it contains some accents caracters.
Take look on this code snipet and i wish you enjoy.

import java.text.Normalizer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import junit.framework.TestCase;

public class TestRegex extends TestCase{
 public void testRegex(){
  String INPUT = "l'postéEç! toto tata a problème à probleme";
  List<String> listCnil = Arrays.asList(new String[]{"l'postéeç!", "a problème"});
  String unAccentInput = unAccent(INPUT);
    
  Set<String> inputWords = new HashSet<String>();
  
  for (String word : listCnil) {
   word = unAccent(word);
   Pattern p = Pattern.compile("\\b\\Q" + word + "\\E\\b", Pattern.CASE_INSENSITIVE);
   Matcher m = p.matcher(unAccentInput);
   
   while (m.find()) {
    String tt = INPUT.substring(m.start(), m.end());
    inputWords.add(tt);
   }
 
  }
  
  for (String str : inputWords) {
   Pattern p = Pattern.compile(\\b\\Q"+str+"\\E\\b", Pattern.CASE_INSENSITIVE);
   Matcher m = p.matcher(INPUT);
   StringBuffer sb = new StringBuffer();
   while (m.find()) {
    String REMP = "<p>"+m.group()+"</p>";
    m.appendReplacement(sb, REMP);
   }
   m.appendTail(sb);
   INPUT=sb.toString();
  }
  System.out.println(INPUT);
 }
 
 
   public static String unAccent(String s) {
       String temp = Normalizer.normalize(s, Normalizer.Form.NFD);
       Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
       return pattern.matcher(temp).replaceAll("");
   }

}

mercredi 19 juin 2013

Multi-threading application issues, with JPA Hibernate

I recently worked with Hibernate JPA 2.0 in multithreading application, and have to deal and manage somme thread safe issues. So I'd like to share this post with who 'll face the same problems in his next devoloppements.

In my case, i try to develop a multi-threading standalone application in which every worker thread can make database transactions (insert or update). These transactions must not delay the thread in any case.

First of all, keep in mind that JPA EntityManager are not synchronized. That means that you cannot create an instance of EntityManager and do all the transactions from that instance. Although, JPA EntityManagerFactory is a synchronized object and hence you can create as many EntityManager you want from an instance of EntityManagerFactory.

My designed possible solution is an EntityManagerHelper class:


public class EntityManagerHelper {

    private static final EntityManagerFactory emf; 
    private static final ThreadLocal<EntityManager> threadLocal;

    static {
        emf = Persistence.createEntityManagerFactory("MyPersistanceUnit");      
        threadLocal = new ThreadLocal<EntityManager>();
    }

    public static EntityManager getEntityManager() {
        EntityManager em = threadLocal.get();

        if (em == null) {
           em = emf.createEntityManager();
          // set your flush mode here 
            threadLocal.set(em);
        }
        return em;
    }

    public static void closeEntityManager() {
        EntityManager em = threadLocal.get();
        if (em != null) {
            em.close();
            threadLocal.set(null);
        }
    }

    public static void closeEntityManagerFactory() {
        emf.close();
    }

    public static void beginTransaction() {
        getEntityManager().getTransaction().begin();
    }

    public static void rollback() {
        getEntityManager().getTransaction().rollback();
    }

    public static void commit() {
        getEntityManager().getTransaction().commit();
    } 
}


This allows me to use the JPA trade safe object EntityManagerFactory to provide the same
JPA EntityManager instance call. 

Next is to call this EntityManagerHelper in seperate class

public class DatabaseService {  
      public static void insertEntity(AnEntity entity){  
           EntityManager em = EntityManagerHelper.getEntityManager();  
           try{  
                EntityManagerHelper.beginTransaction();  
                em.merge(entity);  
                EntityManagerHelper.commit();  
           }catch(Exception e){  
                logger.fatal("Entity Insert Exception:",e);  
                EntityManagerHelper.rollback();  
           }  
           finally{  
                EntityManagerHelper.closeEntityManager();  
           }  
      }  
      public static AnEntity findEntitybyId(int id){  
            EntityManager em = EntityManagerHelper.getEntityManager();  
           AnEntity anEntity = em.find(AnEntity.class, id);  
           EntityManagerHelper.closeEntityManager();  
           return anEntity;  
      }  
 }  

 I hope this'll help.

mardi 28 mai 2013

Framework JAVAASSIST presentation

J'ai été amené lors de mes derniers développements à utiliser et à profiter des avantages des Framework Javaassist. Je le trouve très utile et facile à mettre en place, mais surtout très peu connu. Alors, je met en ligne ce poste pour en partager mon feedback.

Javassist is a sub project of JBoss, Javassist (for Java Programming Assistant) makes Java bytecode manipulation simple. It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. Unlike other similar bytecode editors, Javassist provides two levels of API: source level and bytecode level. If the users use the source-level API, they can edit a class file without knowledge of the specifications of the Java bytecode. The whole API is designed with only the vocabulary of the Java language. You can even specify inserted bytecode in the form of source text; Javassist compiles it on the fly. On the other hand, the bytecode-level API allows the users to directly edit a class file as other editors.

If your application is under Mavan, here is today (28/05/2013) javaassit Mavane's dependency :

<dependency>
     <groupId>javassist</groupId>
     <artifactId>javassist</artifactId>
     <version>3.17.1.GA</version>
</dependency>

A global view of this framework is available under this tutorial . Its main content, allows :
 

1. Reading and writing bytecode
2. ClassPool
3. Class loader
4. Introspection and customization
5. Bytecode level API
6. Generics
7. Varargs
8. J2ME
9. Debug 


I recommand you to take your time, read and explor this tutorial, one can customize and use the java code snippit according to his need.

Here is a javaassist use case example :
Let's suppose that our need is to add AspectJ annotations to a given class, once it is already copiled.
Assuming that our application is under Maven, This can be done by configuring a new Maven goal in the main pom.xml and execute it when "mvn install" or "mvn compile" command is called.


Java code snippet:
The Maven job that add the AspectJ annotation is set in ordinary java Main class. Maven launch it eachtime it generate the byte code. the required configuration in pom.xml file is specified bellow :

<plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>exec-maven-plugin</artifactId>
     <version>1.2</version>
    <executions>
            <execution>
                  <phase>compile</phase>
                  <goals>
                         <goal>java</goal>
                   </goals>
             </execution>
     </executions>
    <configuration>
             <mainClass>myPackage.MyMainclass</mainClass>
             <!--if no argument, skip the tag bellow -->
             <arguments>
                      <argument>arg1</argument>
             </arguments>
   </configuration>
</plugin> 

Now, this is what our concrete class looks like :

@Aspect(value="")
public class MyPointCutAspect{

  @Pointcut(value="")
  public void firstPointCutMeth(MyObj1 obj1){}

  @Pointcut(value="")
  public void secondPointCutMeth(
MyObj2 obj2){}

  @Pointcut(value="")
  public void thirdPointCutMeth(
MyObj3 obj3){}

}



So, the aim of our java class package.myMainclass is to add some custum AspectJ pointcut expressions to MyPointCutAspect methods. If MyPointCutAspect class is compiled like as it is, the generated AspectJ expression is empty, and no AspectJ is bound.

With Javassist we modify and add dynamically custum AspectJ pointcut expression to the generated byte code.

Imagine that we like to add, by javaassit, thoses two AspectJ pointcut expressions :

1- "execution(* myPackage.MyClass.MyMethod1(myPackage.MyObj1)) && args(obj1)" as a value of MyPointCutAspect.firstPointCut method expression.

2- "execution(* myPackage.MyClass.MyMethod2(myPackage.MyObj2)) && args(obj2)" as a value of MyPointCutAspect.secondPintCut method expression.
   All we need is to define it inside the java Main class  myPackage.MyMainclass like below :

public class MyMainclass {
    public static void main(String[] args) throws Exception {
    MyMainclass process= new MyMainclass();
    String expression1=
execution(*  myPackage.MyClass.MyMethod1(myPackage.MyObj1)) && args(obj1)";
   

   String expression2="execution(* myPackage.MyClass.MyMethod2(myPackage.MyObj2)) && args(obj2)";

   process.createDynamicPointCut(
expression1,expression2);
  }


private void createDynamicPointCut(final String expression1,final String expression2) throws ClassNotFoundException {
 try {

  final ClassPool pool = ClassPool.getDefault();
  // Tell Javassist where to look for classes - into our ClassLoader
  pool.appendClassPath(new            LoaderClassPath(getClass().getClassLoader()));
final CtClass dymanicPointCutAspect = pool.get("
myPackage.MyPointCutAspect");
final ClassFile ccFile = dymanicPointCutAspect.getClassFile();
final ConstPool constpool = ccFile.getConstPool();
// add @PointCut annotation to dymanicPointCutAspect's declared
// Methods.
addPointCutAnnotationToMethod(dymanicPointCutAspect.getDeclaredMethod("
firstPointCutMeth"), expression1, constpool);

addPointCutAnnotationToMethod(dymanicPointCutAspect.getDeclaredMethod("
secondPointCutMeth"),expression2, constpool);

addPointCutAnnotationToMethod(dymanicPointCutAspect.getDeclaredMethod("
thirdPointCutMeth"),"", constpool);

dymanicPointCutAspect.writeFile("./target/classes");
 

} catch (NotFoundException e) {     
} catch (IOException e) {
} catch (CannotCompileException e) {
}

}

private void addPointCutAnnotationToMethod(final CtMethod declaredMethod, final String pointCutExpression, final ConstPool constpool)throws ClassNotFoundException {
 

// create @PointCut annotation
AnnotationsAttribute attribute = new AnnotationsAttribute(constpool,AnnotationsAttribute.visibleTag);
Annotation pointCutAnnot = new Annotation("org.aspectj.lang.annotation.Pointcut", constpool);
pointCutAnnot.addMemberValue("value", new StringMemberValue(pointCutExpression, constpool));
attribute.addAnnotation(pointCutAnnot);

// add @PointCut annotation to method
  declaredMethod.getMethodInfo().addAttribute(attribute);
System.out.println("--method -- " + declaredMethod.getName()+ "  -- the annotation "+ Arrays.toString(declaredMethod.getAnnotations()));
}


}


Now, any mvn install command call, add automatically those expression to the given method.

Hope you enjoy.