我有一个用于 Web 服务的 EJB EAR 应用程序,部署在 Glassfish 3.0.1 服务器上。所有依赖项都由 maven 加载,关于 pom.xml。我正在使用 wsimport 从 WSDL 文件生成类。一切都很完美。
然后由于一些性能问题,我不得不为 mybatis 查询实现缓存。打开缓存后,我意识到我的类需要可序列化。这不是问题。
<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings>
<xjc:serializable uid="1" />
</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>
应用程序已编译和部署,但是当我第二次从soapUI 调用Web 服务操作(第一次正常,缓存为空)时,出现以下错误。
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.cache.CacheException: Error deserializing object. Cause: java.lang.ClassNotFoundException: cz.cpost.esb.cenik.schema.CountryType
### Cause: org.apache.ibatis.cache.CacheException: Error deserializing object. Cause: java.lang.ClassNotFoundException: cz.cpost.esb.cenik.schema.CountryType
... some code ommited ...
Caused by: org.apache.ibatis.cache.CacheException: Error deserializing object. Cause: java.lang.ClassNotFoundException: cz.cpost.esb.cenik.schema.CountryType
at org.apache.ibatis.cache.decorators.SerializedCache.deserialize(SerializedCache.java:79)
at org.apache.ibatis.cache.decorators.SerializedCache.getObject(SerializedCache.java:35)
at org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:35)
at org.apache.ibatis.cache.decorators.SynchronizedCache.getObject(SynchronizedCache.java:40)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:56)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:78)
... 83 more
Caused by: java.lang.ClassNotFoundException: cz.cpost.esb.cenik.schema.CountryType
at com.sun.enterprise.loader.ASURLClassLoader.findClassData(ASURLClassLoader.java:713)
at com.sun.enterprise.loader.ASURLClassLoader.findClass(ASURLClassLoader.java:626)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at java.util.ArrayList.readObject(ArrayList.java:593)
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 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at org.apache.ibatis.cache.decorators.SerializedCache.deserialize(SerializedCache.java:76)
... 88 more
似乎当应用程序尝试从缓存中获取数据时,找不到对象 CountryType。我不知道这怎么可能,我在 Maven 和缓存方面还很新。
Maven构建元素:
<build>
<resources>
<resource>
<targetPath>META-INF/wsdl</targetPath>
<directory>src/wsdl</directory>
<includes/>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes/>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<keep>true</keep>
<wsdlFiles>
<wsdlFile>CenikServices-v2.0.wsdl</wsdlFile>
</wsdlFiles>
<packageName>cz.cpost.esb.cenik.schema</packageName>
<staleFile>${project.build.directory}/jaxws/stale/cenik.stale</staleFile>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/jaxb-bindings.xml</bindingFile>
</bindingFiles>
</configuration>
<id>wsimport-generate-cenik</id>
<phase>generate-sources</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>webservices-api</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<configuration>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
<destDir>${project.build.directory}/classes</destDir>
<xnocompile>true</xnocompile>
<verbose>true</verbose>
<extension>true</extension>
<catalog>${basedir}/src/jax-ws-catalog.xml</catalog>
<target>2.0</target>
</configuration>
</plugin>
</plugins>
</build>
映射器配置中的缓存配置:
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<property name="timeToIdleSeconds" value="7200"/>
<property name="timeToLiveSeconds" value="28800"/>
<property name="maxElementsInMemory" value="5000"/>
<property name="maxElementsOnDisk" value="10000"/>
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
我虽然我的源不在类路径中,但我将归档元素放入耳 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cz.cpost.esb</groupId>
<artifactId>cenikservices-ear</artifactId>
<version>2.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ear</artifactId>
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>cenikservices-ejb</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.5</version>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<ejbModule>
<groupId>${project.groupId}</groupId>
<artifactId>cenikservices-ejb</artifactId>
</ejbModule>
</modules>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
EAR文件结构:
但是问题没有解决。为什么应用程序找不到打包在 cenikservices-ejb-2.0.jar 中的生成源?
更新
我在 EJB 类的构造函数中添加了行
import org.apache.ibatis.io.Resources;
...
public CenikEJB() {
Resources.setDefaultClassLoader(this.getClass().getClassLoader()); // added
this.sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory();
}
但在 ASURLClassLoader 上仍然出现相同的错误 :-( 我测试过,如果类 CountryType 在 EJB 方法中可用并且它是可用的。我在日志中看到SUCCESS 。
@Override
public List<CountryType> listCountry(Integer codeTask, String langAlfaCode) throws CenikFault {
methodName = "Cenik.listCountry";
SqlSession session = this.sqlSessionFactory.openSession();
try {
this.getClass().getClassLoader().loadClass("cz.cpost.esb.cenik.schema.CountryType");
ccpLogger.info( "SUCCESS - Pokus o nalezeni tridy CountryType vysel");
} catch (ClassNotFoundException ex) {
ccpLogger.info("FAIL - Pokus o nalezeni tridy CountryType nevysel",ex);
}
try
{
ListCountryType param = this.of.createListCountryType();
param.setCodeTask(codeTask);
param.setLangAlfaCode(langAlfaCode);
// ziskat seznam zemi pomoci SQL procedury
List seznamZemi = session.selectList("Cenik.getListCountry", param);
return seznamZemi;
} catch (IllegalArgumentException ex) {
ccpLogger.error(methodName,ex);
...
} catch (Exception ex) {
ccpLogger.error(methodName,ex);
...
} finally {
session.close();
}
}