sobota, 1 sierpnia 2009

Seam z EhCache

W poprzednim wpisie wygenerowaliśmy sobie pierwszą aplikację Seamową przy pomocy wtyczki JBoss Tools.

Sposób bardzo fajny do szybkiej prezentacji, ale nie oszukujmy się, jest to sposób dobry dla dziewczyn. Do poważniejszych rozwiązań się nie nadaje.
Głównym minusem jest brak skryptu budującego aplikację, czy to antowego, czy to mavenowego.

Dlatego w dzisiejszym wpisie wygenerujemy sobie prostą aplikację Seamową, przy pomocy narzędzia seam-gen. Kilka dni temu światłu dziennemu ukazał się Seam 2.2.0.GA, ale ja posłużę się wersją 2.1.1.GA, głównie dlatego, że mam już ją zainstalowaną.

Wchodzę zatem do katalogu, w którym zainstalowałem Seama i konfiguruję go wykonując polecenie
./seam setup

mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam setup
SEAM_HOME: /opt/jboss-seam-2.1.1.GA
Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen
Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml

init:

setup:
[echo] Welcome to seam-gen :-)
[input] Enter your Java project workspace (the directory that contains your Seam projects) [/home/mateusz/priv/workspace/] [/home/mateusz/priv/workspace/]

[input] Enter your JBoss AS home directory [/opt/jboss-5.0.1.GA/] [/opt/jboss-5.0.1.GA/]

[input] Enter the project name [seam_test] [seam_test]

[echo] Accepted project name as: seam_test
[input] Do you want to use ICEfaces instead of RichFaces [n] (y, [n])

[input] skipping input as property icefaces.home.new has already been set.
[input] Select a RichFaces skin [ruby] (blueSky, classic, deepMarine, DEFAULT, emeraldTown, japanCherry, [ruby], wine)

[input] Is this project deployed as an EAR (with EJB components) or a WAR (with no EJB support) [ear] ([ear], war)

[input] Enter the Java package name for your session beans [pl.matt.session] [pl.matt.session]

[input] Enter the Java package name for your entity beans [pl.matt.model] [pl.matt.model]

[input] Enter the Java package name for your test cases [pl.matt.test] [pl.matt.test]

[input] What kind of database are you using? [mysql] (hsql, [mysql], oracle, postgres, mssql, db2, sybase, enterprisedb, h2)

[input] Enter the Hibernate dialect for your database [org.hibernate.dialect.MySQLInnoDBDialect] [org.hibernate.dialect.MySQLInnoDBDialect]

[input] Enter the filesystem path to the JDBC driver jar [/opt/jboss-seam-2.1.1.GA/lib/hsqldb.jar] [/opt/jboss-seam-2.1.1.GA/lib/hsqldb.jar]
/home/mateusz/java/lib/mysql-connector-java-5.1.7-bin.jar
[input] Enter JDBC driver class for your database [com.mysql.jdbc.Driver] [com.mysql.jdbc.Driver]

[input] Enter the JDBC URL for your database [jdbc:mysql:///test] [jdbc:mysql:///test]

[input] Enter database username [xxx] [xxx]

[input] Enter database password [xxx] [xxx]

[input] skipping input as property hibernate.default_schema.entered has already been set.
[input] Enter the database catalog name (it is OK to leave this blank) [] []

[input] Are you working with tables that already exist in the database? [n] (y, [n])

[input] Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n])

[delete] Deleting: /opt/jboss-seam-2.1.1.GA/seam-gen/build.properties
[propertyfile] Creating new property file: /opt/jboss-seam-2.1.1.GA/seam-gen/build.properties
[echo] Installing JDBC driver jar to JBoss AS
[echo] Type './seam create-project' to create the new project


podaję ścieżki do przestrzeni roboczej, do serwera JBoss, parametry bazy danych, nazwy pakietów i inne ustawienia aplikacji.

następnie tworzę projekt poleceniem
./seam create-project


mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam create-project
SEAM_HOME: /opt/jboss-seam-2.1.1.GA
Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen
Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml

init:

init-properties:
[echo] /opt/jboss-5.0.1.GA/

validate-workspace:

validate-project:

icefaces-staging-copy:

initcopy:

initpoms:
[echo] Setting up dependencies
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[artifact:install] [INFO] Installing /opt/jboss-seam-2.1.1.GA/classes/poms/root.pom to /home/mateusz/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[artifact:install] [INFO] Installing /opt/jboss-seam-2.1.1.GA/classes/poms/parent.pom to /home/mateusz/.m2/repository/org/jboss/seam/parent/2.1.1.GA/parent-2.1.1.GA.pom
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms
[copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms

copyseam:

copyseamdependencies:

copyjbossembedded:

copy-icefaces-home:

copy-icefaces-maven:

copy-lib:
[echo] Copying Seam and dependencies to the /home/mateusz/priv/workspace//seam_test/lib directory...
[copy] Copying 121 files to /home/mateusz/priv/workspace/seam_test/lib
[copy] Copied 5 empty directories to 2 empty directories under /home/mateusz/priv/workspace/seam_test/lib
[echo] Copying JBoss Embedded configuration to the /home/mateusz/priv/workspace//seam_test/bootstrap directory...
[copy] Copying 30 files to /home/mateusz/priv/workspace/seam_test/bootstrap

file-copy-war:

file-copy-ear:
[echo] Copying resources needed for EAR deployment to the /home/mateusz/priv/workspace//seam_test/resources directory...
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources/WEB-INF
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 7 files to /home/mateusz/priv/workspace/seam_test/resources

setup-filters:

file-copy:
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 11 files to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 4 files to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/.settings
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test
[mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/nbproject
[copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test/nbproject
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources
[copy] Copying 12 files to /home/mateusz/priv/workspace/seam_test/view
[copy] Copying 9 files to /home/mateusz/priv/workspace/seam_test/view
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/src/hot/pl/matt/session
[copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test
[mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/src/main/pl/matt/model
[mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/src/test/pl/matt/test
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/src/test

create-project:
[echo] A new Seam project named 'seam_test' was created in the /home/mateusz/priv/workspace/ directory
[echo] Type './seam explode' and go to http://localhost:8080/seam_test
[echo] Eclipse Users: Import the project using File > Import... > Existing Projects into Workspace, set the root directory to /home/mateusz/priv/workspace/, then select the project named seam_test
[echo] NetBeans Users: Open the project using File > Open project... and select the project folder /home/mateusz/priv/workspace//seam_test
[echo] IDEA Users: Open the project using File > Open project... and select the file /home/mateusz/priv/workspace//seam_test/seam_test.ipr

BUILD SUCCESSFUL


i zgodnie z instrukcją

Eclipse Users: Import the project using File > Import... > Existing Projects into Workspace, set the root directory to /home/mateusz/priv/workspace/, then select the project named seam_test

importuję projekt do Eclipsa.

W pakiecie pl.matt.model tworzę klasę Employee

package pl.matt.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.Max;
import org.hibernate.validator.Min;
import org.hibernate.validator.NotNull;

@Entity
@Table(name="employees")
public class Employee {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Length(max=128)
@NotNull
private String name;

@Column(length=128)
@NotNull
private String surname;

@Email
@NotNull
@Column(length=128)
private String email;

@Min(0)
@Max(130)
@NotNull
private int age;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSurname() {
return surname;
}

public void setSurname(String sureName) {
this.surname = sureName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}


i generuję do niej prostego CRUDa poleceniem
./seam generate-ui

mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam generate-ui
SEAM_HOME: /opt/jboss-seam-2.1.1.GA
Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen
Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml

init:

init-properties:
[echo] /opt/jboss-5.0.1.GA/

validate-workspace:

validate-project:

init-generate:

generate-ui:
[echo] Building project 'seam_test' to generate views and controllers

init:

groovy.compile:

groovy.copy:

compile:

copyclasses:

jar:
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/exploded-archives/seam_test.ear/seam_test.jar/META-INF
[copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/exploded-archives/seam_test.ear/seam_test.jar
[hibernate] Executing Hibernate Tool with a JPA Configuration
[hibernate] 1. task: generic exportertemplate: view/list.xhtml.ftl
[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.annotations.Version
[hibernate] INFO: Hibernate Annotations 3.3.0.GA
[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment
[hibernate] INFO: Hibernate 3.2.4.sp1
[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment
[hibernate] INFO: hibernate.properties not found
[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment buildBytecodeProvider
[hibernate] INFO: Bytecode provider name : cglib
[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment
[hibernate] INFO: using JDK 1.4 java.sql.Timestamp handling
[hibernate] 2009-08-01 18:56:21 org.hibernate.ejb.Version
[hibernate] INFO: Hibernate EntityManager 3.3.1.GA
[hibernate] 2009-08-01 18:56:22 org.hibernate.cfg.AnnotationBinder bindClass
[hibernate] INFO: Binding entity from annotated class: pl.matt.model.Employee
[hibernate] 2009-08-01 18:56:22 org.hibernate.cfg.annotations.EntityBinder bindTable
[hibernate] INFO: Bind entity pl.matt.model.Employee on table employees
[hibernate] 2009-08-01 18:56:22 org.hibernate.validator.Version
[hibernate] INFO: Hibernate Validator 3.0.0.GA
[hibernate] 2009-08-01 18:56:22 org.hibernate.tool.Version
[hibernate] INFO: Hibernate Tools 3.2.2.GA
[hibernate] 2. task: generic exportertemplate: view/view.xhtml.ftl
[hibernate] 3. task: generic exportertemplate: view/view.page.xml.ftl
[hibernate] 4. task: generic exportertemplate: view/edit.xhtml.ftl
[hibernate] 5. task: generic exportertemplate: view/edit.page.xml.ftl
[hibernate] 6. task: generic exportertemplate: src/EntityList.java.ftl
[hibernate] 7. task: generic exportertemplate: view/list.page.xml.ftl
[hibernate] 8. task: generic exportertemplate: src/EntityHome.java.ftl
[hibernate] 9. task: generic exportertemplate: view/layout/menu.xhtml.ftl
[javaformatter] Java formatting of 3 files completed. Skipped 0 file(s).
[echo] Type './seam restart' and go to http://localhost:8080/seam_test

BUILD SUCCESSFUL
Total time: 4 seconds



Uruchamiam JBossa i wchodzę na adres:
http://localhost:8080/seam_test/
moim oczom ukazuje się znzna już aplikacja


Dodaję zatem jednego użytkownika


i otwieram w trzech zakładkach. Na konsoli JBossa obserwuję zapytania SQL jakie wykonuje aplikacja:

INFO [STDOUT] Hibernate:
select
employee0_.id as id2_0_,
employee0_.age as age2_0_,
employee0_.email as email2_0_,
employee0_.name as name2_0_,
employee0_.surname as surname2_0_
from
employees employee0_
where
employee0_.id=?
INFO [STDOUT] Hibernate:
select
employee0_.id as id2_0_,
employee0_.age as age2_0_,
employee0_.email as email2_0_,
employee0_.name as name2_0_,
employee0_.surname as surname2_0_
from
employees employee0_
where
employee0_.id=?
INFO [STDOUT] Hibernate:
select
employee0_.id as id2_0_,
employee0_.age as age2_0_,
employee0_.email as email2_0_,
employee0_.name as name2_0_,
employee0_.surname as surname2_0_
from
employees employee0_
where
employee0_.id=?


Jak widać, trzy razy tem sam SELECT.

Zakładając, że tylko nasza aplikacja kożysta z bazy danych test, możemy się pokusić, o włączenie pamięci podręcznej drugiego poziomu, która umożliwi wyrugowanie powtarzających się zapytań.

Dostawców pamięci drugiego poziomu jest kilku. Ja się zdecyduję na najbardziej chyba popularny EhCache.

Uzupełniam zatem spis plików jar, znajdujący się w pliku
deployed-jars-ear.list, które chcę aby znalazły się w aplikacji ear o wpisy:

commons-lang.jar
commons-collections.jar
commons-beanutils.jar
richfaces-ui.jar
commons-digester.jar
commons-beanutils.jar
commons-lang.jar
hibernate.jar
hibernate-all.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
hibernate-validator.jar
cglib.jar
asm.jar
ehcache.jar


w pliku
persistence-dev.xml
dodaję wpisy


<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />


Cały plik wygląda następująco:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for dev profile -->
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">

<persistence-unit name="seam_test">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/seam_testDatasource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="jboss.entity.manager.factory.jndi.name"
value="java:/seam_testEntityManagerFactory" />
<property name="hibernate.cache.use_second_level_cache"
value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
</properties>
</persistence-unit>

</persistence>

natomiast klasę Employee dekoruję adnotacją

@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)


i restartuję aplikację.
Start serwera kończy się komunikatem błędu:


ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=seam_test.ear/seam_test.jar#seam_test state=Create
java.lang.IllegalArgumentException: Cache name cannot contain '/' characters.
at net.sf.ehcache.Cache.setName(Cache.java:1272)
at net.sf.ehcache.CacheManager.addCache(CacheManager.java:501)
at org.hibernate.cache.EhCacheProvider.buildCache(EhCacheProvider.java:87)
at org.hibernate.cache.CacheFactory.createCache(CacheFactory.java:61)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:214)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:730)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:127)
at org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:301)
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:698)
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)


O co chodzi?

Otuż... chodz o błąd, który byłem tak uprzejmy i zgłosiłem.

JBoss wstawia slashe do nazw fragmentów pamięci podręcznej, a EhCache próbuje tworzyć pliki o nazwie takiej jak nazwa fragmentu pamięci podręcznej i ZONK. Co z tym fantem zrobić?

Napisać własny CacheProvider. Wbrew pozorom nie jest to takie trudne.
Tworzę więc klasę
JBoss5EhCacheProvider
która zamieni w nazwach pamięci podręcznej znaki '/' na '_'.


package pl.matt.cache;

import java.util.Properties;

import org.hibernate.cache.Cache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CacheProvider;

public class JBoss5EhCacheProvider implements CacheProvider {

private CacheProvider delegate = new org.hibernate.cache.EhCacheProvider();

@Override
public Cache buildCache(String name, Properties props) throws CacheException {
name = changeName(name);
return delegate.buildCache(name, props);
}

private String changeName(String name) {
if (name != null) {
return name.replace('/', '_');
}
return name;
}

@Override
public boolean isMinimalPutsEnabledByDefault() {
return delegate.isMinimalPutsEnabledByDefault();
}

@Override
public long nextTimestamp() {
return delegate.nextTimestamp();
}

@Override
public void start(Properties arg0) throws CacheException {
delegate.start(arg0);
}

@Override
public void stop() {
delegate.stop();
}

}



i ustawiam ją w pliku persistence-dev.xml jako CacjeProvider.

<property name="hibernate.cache.provider_class" value="pl.matt.cache.JBoss5EhCacheProvider" />


Czas na kolejny restart aplikacji. Chyba się udało...

[ServerImpl] JBoss (Microcontainer) [5.0.1.GA (build: SVNTag=JBoss_5_0_1_GA date=200902232048)] Started in 1m:4s:297ms


Otwieram kilka razy pracownika w różnych zakładkach.
W konsoli widzę:

[STDOUT] Hibernate:
select
employee0_.id as id0_,
employee0_.age as age0_,
employee0_.email as email0_,
employee0_.name as name0_,
employee0_.surname as surname0_
from
employees employee0_ limit ?

tylko raz. Kilka zapytań o obiekty, a do bazy zapytanie poszło jedno.
Sukces pełną gębą.

3 komentarze:

Ryba pisze...

Hej.

Przy wielokrotnych wywołaniach danych, które nie ulegają zmianie zbyt często, faktycznie - warto rozważyć użycie cache. Jednak o ile nowe zapytanie dla nowej zakładki jest w miarę przewidywalne to... :) Taka ciekawostka poniżej.


Do prezentacji encji w tabelkach używamy @DataModel, @Factory. Czasami jednak człowiek, nawet przez przypadek, zboczy z ustalonej ścieżki i wtedy robi się śmiesznie. Jeśli nie potrzebujesz wykorzystywać @DataModelSelection to wypluj listę adnotacją @Out. Spoko, nic ciekawego. Metoda inicjalizująca:

@Factory
public void listSystemAccounts(){
systemAccounts = entityManager. (...)
}

Korzystam z <rich:dataList> do wyświetlenia listy encji Account. Pozbywam się @Factory i robię zamiast tego getter do listy, na szybko wyrzucam wyniki returnem:

public List<Account> getSystemAccounts(){
return entityManager.(...)
}

Myślisz sobie w pośpiechu: "kontrolka wywoła getter, wykona zapytanie i wyświetli listę". Gdzie tkwi błąd? A jaki błąd? Przy wyświetlaniu np. 7 encji Account, do bazy u mnie pójdzie 15 takich samych zapytań :D

Z JSF-ami też trzeba uważać, taka dajmy na to kontrolka listy do wyświetlenia sama w sobie nie zapamięta i zaatakuje u mnie bazę przy każdej pozycji nawet dwa razy :)

WooKasZ pisze...

ciężki ten Seam... ja nawet tego uruchomić nie mogę bo mi rzucą OutOfMemoryException ;o
A mam 3GB ramu

MZ pisze...

coś przekombinowałeś... może JBossa odpalasz z 64 megabajtami? U mnie działa normalnie, bez kombinowania (w run.conf mam JAVA_OPTS="-Xms128m -Xmx512m ...") czyli nie więcej niż 0.5 giga i działa.