Do celów edukacyjnych posiadam napisaną aplikację we frameworku JBoss Seam. Niedawno pisałem, że ukazała się nowa wersja serwera aplikacji JBoss, dlatego też postanowiłem spróbować uruchomić mój poligon doświadczalny na nowym serwerze. Oto konfiguracja mojej aplikacji:
- EJB 3.0, JavaBeans, JPA, JSF
- JBoss Seam 2.1.0.SP1
- RichFaces 3.2.2.GA
- Hibernate 3.2.4.sp1 (dialekt PostgreSQL)
Używane przeze mnie IDE to Eclipse Ganymede, wraz z zestawem wtyczek JBoss Tools. Połączenie to stanowi bardzo dobre środowisko do tworzenia aplikacji we frameworku JBoss Seam. Aplikacje uruchamiam na gorąco na serwerze JBoss AS za pomocą skryptu Anta — nowe pliki są kompilowane i kopiowane do katalogu deploy serwera JBoss. Na tym etapie nie przewiduję żadnych zmian w konfiguracji.
Po podmianie ścieżki do nowego serwera spróbowałem uruchomić aplikację (a nóż widelec…). Jak można było łatwo przewidzieć — nie uruchomiła się.
Moja aplikacja używa cacheowania encji. Okazało się, że w tym temacie zaszły duże zmiany w nowej wersji serwera. Na szczęście dostępna jest bardzo dobra dokumentacja, która pozwoliła mi się wstępnie rozeznać w temacie. Od wersji 5.0 pamięcią podręczną w serwerze JBoss AS zarządza nowa usługa — CacheManager. Na stronie z dokumentacją nowej usługi znajduje się szczegółowa informacja w jaki sposób skonfigurować aplikację — okazało się to bardzo pomocne :)
Dokonałem zmian zgodnych z sekcją Usage with JPA and Hibernate Entity Clustering dokumentu i uruchomiłem ponownie aplikację. Posunąłem się tylko o mały krok naprzód, ponieważ JBoss przywitał mnie wyjątkiem:
20:03:35,416 ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=system.ear/system.jar#system state=Create javax.persistence.PersistenceException: [PersistenceUnit: system] Unable to build EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:132) at org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:311) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.reflect.plugins.introspection.ReflectionUtils.invoke(ReflectionUtils.java:59) at org.jboss.reflect.plugins.introspection.ReflectMethodInfoImpl.invoke(ReflectMethodInfoImpl.java:150) at org.jboss.joinpoint.plugins.BasicMethodJoinPoint.dispatch(BasicMethodJoinPoint.java:66) at org.jboss.kernel.plugins.dependency.KernelControllerContextAction$JoinpointDispatchWrapper.execute(KernelControllerContextAction.java:241) at org.jboss.kernel.plugins.dependency.ExecutionWrapper.execute(ExecutionWrapper.java:47) at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchExecutionWrapper(KernelControllerContextAction.java:109) at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchJoinPoint(KernelControllerContextAction.java:70) at org.jboss.kernel.plugins.dependency.LifecycleAction.installActionInternal(LifecycleAction.java:221) at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction(InstallsAwareAction.java:54) at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction(InstallsAwareAction.java:42) at org.jboss.dependency.plugins.action.SimpleControllerContextAction.simpleInstallAction(SimpleControllerContextAction.java:62) at org.jboss.dependency.plugins.action.AccessControllerContextAction.install(AccessControllerContextAction.java:71) at org.jboss.dependency.plugins.AbstractControllerContextActions.install(AbstractControllerContextActions.java:51) at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348) at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1598) at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:934) at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1062) at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:984) at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:774) at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:540) at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(BeanMetaDataDeployer.java:121) at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(BeanMetaDataDeployer.java:51) at org.jboss.deployers.spi.deployer.helpers.AbstractSimpleRealDeployer.internalDeploy(AbstractSimpleRealDeployer.java:62) at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(AbstractRealDeployer.java:50) at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:171) at org.jboss.deployers.plugins.deployers.DeployersImpl.doDeploy(DeployersImpl.java:1439) at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1157) at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1178) at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1210) at org.jboss.deployers.plugins.deployers.DeployersImpl.install(DeployersImpl.java:1098) at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348) at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1598) at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:934) at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1062) at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:984) at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:822) at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:553) at org.jboss.deployers.plugins.deployers.DeployersImpl.process(DeployersImpl.java:781) at org.jboss.deployers.plugins.main.MainDeployerImpl.process(MainDeployerImpl.java:545) at org.jboss.system.server.profileservice.ProfileServiceBootstrap.loadProfile(ProfileServiceBootstrap.java:304) at org.jboss.system.server.profileservice.ProfileServiceBootstrap.start(ProfileServiceBootstrap.java:205) at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:405) at org.jboss.Main.boot(Main.java:209) at org.jboss.Main$1.run(Main.java:547) at java.lang.Thread.run(Thread.java:619) Caused by: org.hibernate.cache.CacheException: unsupported access type [nonstrict-read-write] at org.hibernate.cache.jbc2.entity.EntityRegionImpl.buildAccessStrategy(EntityRegionImpl.java:66) at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:256) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327) at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669) ... 51 more
Moje encje wyglądają mniej więcej tak:
@Name("rolePermission")
@Entity
@Table(name = "role_permissions")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@SequenceGenerator(name = "role_permission_seq", sequenceName = "role_permission_seq")
public class RolePermission implements Serializable, SystemEntity {
...
}
Zgłupiałem. Czyżby ta strategia dostępu do encji nie była wspierana? Przecież w JBoss AS 4.2.x była! Kod źródłowy klasy org.hibernate.cache.jbc2.entity.EntityRegionImpl okazał się pomocny.
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
if (AccessType.READ_ONLY.equals(accessType)) {
return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
}
if (AccessType.TRANSACTIONAL.equals(accessType)) {
return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
}
// todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
throw new CacheException("unsupported access type [" + accessType.getName() + "]");
}
Ten TODO wyjaśnia wszystko…
Atrybut usage adnotacji @org.hibernate.annotations.Cache ustala jeden z pięciu typów strategii użycia pamięci podręcznej:
NONE— pamięć nie jest używana,READ_ONLY— aplikacja czyta obiekty, ale nigdy ich nie modyfikuje,READ_WRITE— dane mogą być odczytywane jak i modyfikowane,NONSTRICT_READ_WRITE— dane są głównie odczytywane, modyfikacje mogą wystąpić, ale są rzadkie,TRANSACTIONAL— używany przy providerach w pełni wspierających transakcje.
Do tej pory używałem CacheConcurrencyStrategy.NONSTRICT_READ_WRITE z uwagi na wydajność. Wygląda na to, że trzeba się pożegnać z tym trybem na rzecz CacheConcurrencyStrategy.TRANSACTIONAL.
Kolejna próba uruchomienia aplikacji zakończyła się sukcesem, jeżeli można tak powiedzieć. Po drodze musiałem poprawić jeden komponent. Przy okzji hot deploy’u nowej wersji odkryłem błąd — aplikacja uruchamia się, po czym chwilę później zamyka się — bez jakichkolwiek błędów, czy ostrzeżeń!
20:43:38,856 INFO [SeamFilter] Initializing filter: org.jboss.seam.web.identityFilter 20:43:38,864 INFO [[/system]] org.tuckey.web.filters.urlrewrite.UrlRewriteFilter INFO: conf reload check performed each request 20:43:38,923 INFO [[/system]] org.tuckey.web.filters.urlrewrite.UrlRewriteFilter INFO: loaded (conf ok) 20:43:44,104 INFO [TomcatDeployment] undeploy, ctxPath=/system, vfsUrl=system.ear/system.war 20:43:44,108 INFO [[/system]] org.tuckey.web.filters.urlrewrite.UrlRewriteFilter INFO: destroy called
Bardzo irytujące — nie da się przez to pracować, ponieważ deploy trwa w takim przypadku ok. 10 minut (sic!). Muszę poczytać o hot deploy’u w nowej wersji, bo to powinno działać! Kupiłem sobie książkę JBoss in Action — będzie dobry pretekst aby ją przeczytać :) Tymczasem wracam do starego, dobrego JBoss AS 4.2.3.


Marku, czy udało Ci się jakoś zwalczyć problem niespodzewanego zamykania się aplikacji zaraz po jej deploymencie?
Włąśnei natknąłem się na to w JBossAS 5.1.0.GA i nie mam pomysłu jak z tym walczyć (http://seamframework.org/Community/InfiniteLoopOfRedeploymentsJBoss5xOfProjectFromSeamgen)
Pozdrawiam
Niestety nie. Zostawiłem ten temat. Co prawda rozmawiałem Z Pete Muirem o tym w czasie gdy był wydawany JBoss AS 5.0.1.GA, powiedział, że to zostało poprawione. Nie sprawdzałem, co później się działo z tym…
Istotnie wersja JBossa 5.0.1.GA nie sprawia takich trudności, jednak 5.1.0.GA niestety tak :(
Przesiadłem się z 5.0.1 gdyż są tam jakieś dziwne problemy z hot-deploymentem, a 5.1.0 radzi sobie nieco lepiej.
Wydaje mi się jednak, że ciagle leaderem pod tym względem pozostaje Boss AS 4.x.
Rzuć okiem na: JBAS-6590.
Dzięki za namiar na issue JBossa. Spróbowałem zrobić tak jak opisałem tutaj http://seamframework.org/Community/InfiniteLoopOfRedeploymentsJBoss5xOfProjectFromSeamgen#comment81810 i narazie jest przyzwoicie – nie redeployuje bez końca.
Nie ma za co! Tak, ja też zastosowałem ten hack do wersji 5.0.0, jednak miałem z tym jakiś problem później, niestety nie pamiętam już jaki :( Kurde, trzeba to w końcu naprawić, żebym tylko wiedział od czego zacząć :)
No nic, powodzenia życzę!
P.S. Możesz zagnieżdżać komentarze :)
ooo, fakt, na przyszłość się przyda info :)
Jakbyś kiedyś w przyszłości … wiedział jak zwalczyć problem to umieść krótką notkę tutaj w konemtarzach, a mnie sie mail dostanie z powiadomieniem :)
Tak też uczynię, bo pewnie za jakiś czas będę musiał napisać coś w Seamie.