codemonkey

2009-12-11

Redeploy-memory-leak on JBoss 4.2.2 figured out

Filed under: Java — Tags: , , , , , — Johan @ 20:39

We have long had the problem that redeploying our Java EE application on JBoss 4.2.2 was leaking lots of memory. We have a quite large enterprise app and we are talking about 10 of megabytes permgen per redeploy resulting in a permgen out of memory exception crashing the Jboss instance after a few redeploys.

Searching the net we have found lots of “explanations” and “solutions” going from class generation (CGLIB or Javassist bugs) to just increasing the maximum permgen size or switching to another JVM that does not have a fixed part of its memory for classes (and actually just postponing the crash).

After spending some time with heapdumps and MAT (eclipse memory analyzer, great application by the way) I figured this out: the hibernate usertype for enums is the culprit. It keeps a list of the enum values and the java enums have a static references to the classloader making it impossible for the Jboss classloaders to be garbage collected after an application has been undeployed. The classloader holds a reference to each class in the previously deployed application that in turn cannot be garbage collected.

I found #HHH-4317 in the Hibernate issue management system that describes the problem. We have not figured out a solution yet though, I think it probably will end with a patched hibernate on our installation sites (keeping some kind of weak references to the enum values in EnumType).

2009-11-10

Setup Hibernate and EhCache MBeans on JBoss

Filed under: Java — Tags: , , , , — Johan @ 00:24

Lately I have been setting up some second level cache for Hibernate to speed up our JEE application at work. To find out how good the cache was configured I wanted to setup the Hibernate statistics MBean and the EhCache monitoring MBeans so that I could do some monitoring with JConsole.

The problem was that we use Hibernate as a JPA provider rather than directly which made it a bit tricky to get the MBeans up and running. This is how I did it.

First tell JBoss to publish the entity manager on JNDI by putting this line in your persistence.xml-file: <property name="jboss.entity.manager.jndi.name" value="myapp/EntityManager" />. Also make sure you use the net.sf.ehcache.hibernate.SingletonEhCacheProvider second level cache provider.

Finally create a JBoss service, something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Local(MonitoringServiceMBean.class)
@Service(objectName = "myapp:service=monitoring")
@Management(MonitoringServiceMBean.class)
public class MonitoringService implements MonitoringServiceMBean {
 
    private static final Logger LOGGER = Logger.getLogger(MonitoringService.class);
 
    public void start() throws Exception {
        LOGGER.info("MonitoringService - Starting");
 
        // We need to do it this way to register beans on the JBoss mbean server
        MBeanServer mbs = MBeanServerFactory.findMBeanServer(null).get(0);
 
 
        ObjectName on = new ObjectName("Hibernate:type=statistics,application=myapp");
 
        // Enable Hibernate JMX Statistics
        StatisticsService statsMBean = new StatisticsService();
        SessionFactory sf = getSessionFactory();
        statsMBean.setSessionFactory(sf);
        statsMBean.setStatisticsEnabled(true);
        mbs.registerMBean(statsMBean, on);
 
 
        // Enable Ehcache JMX Statistics
        // Use CacheManager.getInstance() instead of new CacheManager()
        // as net.sf.ehcache.hibernate.SingletonEhCacheProvider is used
        // to ensure reference to the same CacheManager instance as used
        // by Hibernate
        CacheManager cacheMgr = CacheManager.getInstance();
        ManagementService.registerMBeans(cacheMgr, mbs, true, true, true, true);
    }
 
   ...

Now you will have access to cache and entity statistics through JConsole for your Hibernate JEE app.

2009-11-02

Audit logging with JPA listeners on JBoss

Filed under: Java — Tags: , , , , — Johan @ 22:57

JPA listeners seems like a good candidate for providing audit data (like for example user and timestamp of last change) to entities on every write to the database. The problem is that JPA listeners does not have the luxury of injection like JEE interceptors and EJBs do. This makes it hard to access the SessionContext and the caller principal.

In the book “Real World Java EE” Adam Bien (great book by the way) proposes a solution using ThreadLocal to store the principal. If you do manage your transactions from a remote client you will get a different thread for each EJB call and then another one for transaction commit from the client making the ThreadLocal solution impossible to use.

If you use JBoss as your JEE container you can use org.jboss.tm.TransactionLocal instead. It will bind data to the current transaction.

Example interceptor that should be used on the EJB:s:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AuditInjector {
 
   @Resource
   private SessionContext sessionContext;
 
   private final TransactionLocal transactionLocal = new TransactionLocal();
 
   @AroundInvoke
   public void storePrincipalInTransaction(InvocationContext ic) throws Exception {
      Principal principal = sessionContext.getCallerPrincipal();
      transactionLocal.set(principal);
      return ic.proceed();
   }
}

Example jpa listener:

1
2
3
4
5
6
7
8
9
10
11
public class AuditListener {
 
   private static final TransactionLocal transactionLocal = new TransactionLocal();
 
   @PreUpdate
   @PrePersist
   public void setAuditData(AuditableEntity entity) {
      entity.setTimestamp(new Date());
      entity.setUsername(((Principal)transactionLocal.get()).getName());
   }
}

This exact code is not tested and is intended as an idea rather than a working example to copy and paste. We do use a similiar solution in our JEE application that does work well.

Migrating to english

Filed under: Övrigt — Johan @ 10:13

I was thinking about how the target audience for this blog was severely limited by writing in swedish and decided to start to write posts in english instead. I’ll leave to old swedish posts for now but all new posts will be in english.

2009-09-01

Os X Snow Leopard

Filed under: Mac — Tags: , , , , — Johan @ 12:03

Har precis installerat apples uppdatering till 10.6. Gick hyffsat snabbt och jag tjänade på något märkligt sätt 16 Gb i ledigt diskutrymme på det.

Alla program som följer med operativsystemet känns lite mer responsiva. Javascripttunga sidor som t.ex. google maps känns avsevärt mycket snabbare i Safari än förut. Mailprogrammet startar på nolltid vilket det kanske inte riktigt gjorde förut. Java verkar inte ha fått någon prestandaboost – Netbeans och JBoss känns som om de går med samma fart som förut.

Försökte testa exchangestödet men jobbets server var visst version 2003 och stödet är för 2007. Vi använder dessutom något slags gammal funktion som kallas “public folders” för våra gemensamma kalendrar etc. som microsoft rekommenderar folk att sluta med och som inte stöds.

Standbyläget är avsevärt mycket snabbare – vi snackar 4 sekunder efter att jag stängt ihop laptopen tills datorn faktiskt sover mot runt 15-20 sekunder förut.

2009-07-23

Hibernate och 2:nd level cache på JBoss 4

Filed under: Java — Johan @ 20:48

Idag har jag pysslat lite med hibernates “second level cache” för att snabba upp blodcentralssystemet som jag jobbar med om dagarna. Det finns en hel del att läsa om det hela (devx, dynatrace blog osv.).

Problemet var dock att EhCache som alla exempel använder fick fnatt när jag re-deployade vår enterprise applikation på JBoss.

“net.sf.ehcache.CacheException: Error configuring from null. Initial cause was null” tyckte EhCache. Till slut upptäckte jag att det finns en cache-provider inbyggd i JBoss 4 och när jag konfigurerade hibernate att använda den fungerade det vips finfint att redeploya.

Bra PDF om hibernate och jboss cache (kolla en bit ned, länken “Using JBoss Cache 2 as a Hibernate Second Level Cache”)

2009-07-04

Samsung TV med och DLNA-server på Linux

Filed under: linux — Tags: , , , , , , , , , , — Johan @ 16:50

Jag köpte en sjukt stor TV från Samsung (UE 46B 7070 heter modellen) häromdagen som har stöd för att visa/spela film, bilder och musik över nätverket. Om man kopierar över film på USB-minne så verkar den klara åtminstone divx/avi och mkv-filer galant.

Uppspelning över nätverket sker genom stöd för något slags standard som heter DLNA. Samsung skickar med en servermjukvara “PC Share Manager” som är bara för windows (som jag inte ens kunnat testa eftersom jag kör linux och osx hemma + att min CD-spelare i laptopen precis kastat in handduken).

Efter att ha tragglat fram och tillbaka med mediatomb som jag hade installerat sedan tidigare för att strömma film till mitt PS3. Det gick bra att bläddra bland de filmer som fanns tillgängliga men så fort man försökte spela upp något fick man “formatet stöds ej”. Efter lite sökande på nätet bestämde jag mig för att testa coherence. Fick lov att maskera av ett gäng paket men det var hyffsat lätt att installera på min gentoo-server.

Utan något speciellt trixande med coherence-konfigurationen (lade upp en utdelning av katalogen jag har film och sådant i med FSShare) kan jag nu åtminstone spela mp3-filer och kolla på jpeg-bilder från linux-servern på TV:n. Filmerna får jag fortfarande “formatet stöds ej” på desvärre.

2009-06-27

Site för Jee5Unit

Filed under: Java — Tags: — Johan @ 13:29

Nu har jag fått upp ett repositorie och en site för jee5unit så att du också kan byta ut ejb3unit eller börja testa dina entiteter och EJB:er.

http://markatta.com/jee5unit

Deploy och site:deploy till webdav med maven

Filed under: Maven — Tags: , , , , , — Johan @ 13:27

Jag har satt upp mitt nya projekt jee5unit att deploya sina artifakter mot http://markatta.com/maven och projektsajten mot http://markatta.com/jee5unit och stötte under vägen på ett klurigt problem.

När jag satt upp webdav på min apache och sett att det fungerade fint med autentisering så vägrade ändå maven att deploya mot servern. Felmeddelandet jag fick var:

[INFO] Error deploying artifact: Failed to create destination WebDAV collection (directory): /maven/com/markatta/jee5unit/1.0

unable to find valid certification path to requested target

Det visade sig att java inte bryr sig om de rootcert som man installerat på nyckelringen i OSX som alla andra program utan har en egen keystore som går att hitta i filen $JAVA_HOME/lib/security/cacerts.

Eftersom jag inte är miljonär och i vilket fall inte vill ge mina pengar till verisign så har jag servertcertifikat signerade av cacert.org (som jag för övrigt varmt kan rekommendera, funkar skitbra). Cacert.org har ett rootcertifikat som inte finns med bland standardcertifikaten och som jag fått lägga till själv på min nyckelring. Detta cert fick jag då också lov att lägga till i javas keystore.

Så här gjorde jag det:

sudo keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -file root.crt -alias cacert.org

Lösenordet för cacerts-keystoren är (om du inte ändrat det) “changeit” ;P

2009-06-26

tack och adjö ejb3unit

Filed under: Java — Johan @ 12:33

Jag har sedan jag började koda JEE5 använt ett testframework som heter ejb3unit som gör det möjligt att unittesta EJB:er och JPA-entiteter. Från början kändes det väldigt lovande och det har fungerat hyffsat bra. På jobbet har vi dock fått lov att patcha det för att stänga av hibernates fältvalidering eftersom vi ville kunna slänga in entiteter i databasen utan att fylla alla fält med korrekta värden under testerna.

Vi har en datamodell på mellan 400 och 500 klasser på jobbet och rätt bra testcoverage. Sakta men säkert har dock problemen med att ejb3unit inte skalar så bra krypit fram. För att köra våra tester krävdes över 500 Mb minne vilket gjorde att vi fick lov att trixa med byggena och höja default-heapen hela tiden. Det tog också lång tid, igår tog det tre och en halv minut att bygga och testa vårt modellprojekt.

Jag bestämde mig då för att styra upp det hela och skrev igårkväll ihop ett nytt testframework som ersätter ejb3unit i alla fall som vi testar (läsa/skriva entiteter, testa jqpl-queries och named queries, testa ejb:er som använder entitetshanteraren och caller principal).

Totalt blev det ungefär fem klasser istället för ejb3units hundra (man får väl tänka på att det är ett subset av funktionalitet) och det känns fint. Men framförallt: byggtiden på tre och en halv minut blev 32 sekunder, minnesanvändningen på över 500 Mb är nu 27 Mb.

Jag har publicerat projektet på kenai, men de verkar ha lite dåligt stöd för mavenprojekt än så länge så jag skall se under veckan om jag kan lyckas publicera en första-release och projektsite med lite dokumentation.

Projektet på kenai: http://kenai.com/projects/jee5unit

Older Posts »

Powered by WordPress