2013-06-07 1 views
2

У меня есть приложение EAR с EJB для веб-сервисов, развернутое на сервере Glassfish 3.0.1. Все зависимости загружаются maven, относящиеся к pom.xml. Я использую wsimport для генерации классов из файлов WSDL. Все отлично работало.ClassNotFoundException при десериализации данных из кеша

Затем мне пришлось реализовать кэширование запросов mybatis из-за некоторых проблем с производительностью. После того, как я включил кеширование, я понимаю, что мои классы должны быть сериализуемыми. Это не проблема.

<xs:annotation> 
    <xs:appinfo> 
     <jaxb:globalBindings> 
      <xjc:serializable uid="1" /> 
     </jaxb:globalBindings> 
    </xs:appinfo> 
</xs:annotation> 

Применение компилируется и развертывается, но когда я называю работу веб-службы во второй раз (первый раз нормально, кэш пуст) из SoapUI, я получаю следующее сообщение об ошибке.

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:

structure of deployed EAR file

Но проблема не решена. Почему приложение не могло найти сгенерированные источники, упакованные в cenikservices-ejb-2.0.jar?


UPDATE

Я добавил строки в моем классе EJB в его конструктор

import org.apache.ibatis.io.Resources; 
... 
public CenikEJB() { 
    Resources.setDefaultClassLoader(this.getClass().getClassLoader());  // added 
    this.sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory(); 
} 

, но все еще получаю ту же ошибку на ASURLClassLoader :-( Я проверил, если класс CountryType является доступный в EJB-методе, и есть. Я вижу УСПЕХ в журнале.

@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(); 
    } 
} 
+0

У вас есть serialversionUID в рассматриваемом классе? – Thihara

+0

Благодарим за комментарий. Да, у меня есть 'private final static long serialVersionUID = 1L;' во всех моих классах, сгенерированных wsimport. Но serialVersionUID устанавливается одинаково для каждого класса. Это может быть проблема? – Worsik

+0

Нет, если это то же самое, это не должно быть проблемой ... Ну, если нет двух версий со структурными различиями. – Thihara

ответ

2

Проблема в том, что серверная сторона не может загрузить класс cz.cpost.esb.cenik.schema.CountryType.

Наиболее вероятной причиной является то, что файл JAR, который определяет этот класс, не может быть включен в файл EAR, который вы развернули. И наиболее вероятным объяснением этого является то, что файл POM для проекта EAR не имеет требуемой зависимости в требуемой форме.

Обратите внимание, что зависимости должны быть указаны в элементе <dependencies> на верхнем уровне в файле POM; то естькак дочерний элемент элемента <project>.


Первый шаг должен состоять в том, чтобы проверить, действительно ли файл JAR, содержащий этот класс, в развернутом webapp. (Это так, тогда проблема - это что-то еще ...)

Затем вам нужно добавить необходимые зависимости к файлу POM модуля EAR.


UPDATE

На основании дополнительной информации, предоставленной вами, я думаю, что это проблема с загрузкой класса Ibatis'. Похоже, что Ibatis пытается загрузить класс, используя загрузчик классов, который не включает ваши классы. (Я думаю, что Ibatis использует «общие классы» загрузчик класса ... который не включает в себя ваши JARs приложения.)

Очевидно, что исправление сделать это в вашем классе сервлета:

import com.ibatis.common.resources.Resources; 
    ... 
    Resources.setDefaultClassLoader(this.getClass().getClassLoader()); 

Ссылки:

UPDATE # 2

Я предполагаю, что в этот момент ... но это сообщение об ошибке (http://code.google.com/p/mybatis/issues/detail?id=622), кажется, описывающее ошибку в MyBatis 3.x, где setDefaultClassLoader не работает. Кажется, они говорят «зафиксировано в 3.2.2». Я замечаю, что вы используете 3.0.5. Посмотрите, помогает ли обновление зависимости POM к более поздней версии.

Если нет, самое лучшее, что я могу предложить, это прикрепить отладчик к экземпляру Glassfish и посмотреть, можете ли вы выкопать, какой класс загрузчик он использует ... и почему. Кажется довольно ясным, что это is проблема с загрузчиком класса.

+0

EAR включает JAR-файл в корневой каталог, другие источники (зависимости от jar) находятся в папке lib. JAR-файл включает в себя весь пакет __schema__, сгенерированный из wsimport – Worsik

+0

Я редактировал свой вопрос с добавлением структуры EAR. – Worsik

+0

Спасибо за обновление, я попробую завтра на работе – Worsik