2014年4月11日星期五

EAP_001:ehcache war包部署到JBoss上的问题

ehcache war部署在Tomcat7上没问题,但是部署在JBoss 6上有问题。
一查之下,是因为JBoss内置使用的RestEasy和Jersey冲突。
经过仔细研究,记录下解决问题的整个过程,问题终于解决了,更重要的是解决过程中的经验积累。

1.下载 ehcache 
下载地址:http://ehcache.org/downloads/catalog
目前ehcache war 包最新的版本是1.0.0。
选择 ehcache-server-1.0.0-distribution.tar.gz 和 ehcache-standalone-server-1.0.0-distribution.tar.gz。
解压 ehcache-server-1.0.0-distribution.tar.gz,里面会有一个 ehcache-server-1.0.0.war,这就是我们要部署到JBoss上的war文件。

2.下载 JBoss EAP 
下载地址:http://www.jboss.org/jbossas/downloads/
目前JBoss EAP的最新的版本是6.2.0。
解压 jboss-eap-6.2.0.zip。

3. JBoss EAP 6.2.0 运行环境需要使用JDK6,不能使用JDK7
使用JDK7会报出异常:javax.xml.ws.WebServiceException: Unable to create StaticLoggerBinder JAXBContext

4. 在 ehcache war包中的lib目录增加一个jar:slf4j-jdk14-1.5.8.jar
slf4j-jdk14-1.5.8.jar可以在ehcache-standalone-server-1.0.0-distribution.tar.gz中找到。
如果不增加这个jar包,会报出异常:NoDefClass:org.slf4j.impl.StaticLoggerBinder。

5. 重新打包 ehcache war,复制到[jboss_home]/standalone/deployments目录下,然后启动JBoss
在Console中会抛出异常:Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS011232: 只允许一个 JAX-RS 应用程序类别。

6. 在 ehcache war包中的WEB-INF目录下增加一个文件:jboss-deployment-structure.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <deployment>
        <exclude-subsystems>
            <subsystem name="jaxrs"/>
        </exclude-subsystems>
        <exclusions>
            <module name="javaee.api"/>
        </exclusions>
        <dependencies>
            <module name="javax.activation.api" export="true"/>
            <module name="javax.annotation.api" export="true"/>
            <module name="javax.ejb.api" export="true"/>
            <module name="javax.el.api" export="true"/>
            <module name="javax.enterprise.api" export="true"/>
            <module name="javax.enterprise.deploy.api" export="true"/>
            <module name="javax.inject.api" export="true"/>
            <module name="javax.interceptor.api" export="true"/>
            <module name="javax.jms.api" export="true"/>
            <module name="javax.jws.api" export="true"/>
            <module name="javax.mail.api" export="true"/>
            <module name="javax.management.j2ee.api" export="true"/>
            <module name="javax.persistence.api" export="true"/>
            <module name="javax.resource.api" export="true"/>
            <module name="javax.rmi.api" export="true"/>
            <module name="javax.security.auth.message.api" export="true"/>
            <module name="javax.security.jacc.api" export="true"/>
            <module name="javax.servlet.api" export="true"/>
            <module name="javax.servlet.jsp.api" export="true"/>
            <module name="javax.transaction.api" export="true"/>
            <module name="javax.validation.api" export="true"/>
            <module name="javax.xml.bind.api" export="true"/>
            <module name="javax.xml.registry.api" export="true"/>
            <module name="javax.xml.soap.api" export="true"/>
            <module name="javax.xml.ws.api" export="true"/>
            <module name="javax.api" export="true"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>
原理解释:JBoss使用module方式来装载应用需要的模块,如果不需要某些模块,可以在jboss-deployment-structure.xml中将其排除。
因为jboss-deployment-structure.xml是在应用中的,所以被排除的模块只对当前应用有效。
如果需要全局性的排除某些模块,需要修改standalone.xml文件。
对于本例,可以注释:<extension module="org.jboss.as.jaxrs"/>和 <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>这两行。
当然,一般不建议注释全局的module,因为会影响其它应用的使用。

7. 重新打包 ehcache war,复制到[jboss_home]/standalone/deployments目录下,然后启动JBoss
在Console中会抛出异常:com.sun.jersey.core.spi.scanning.ScannerException: The URI scheme vfs of the URI vfs:…… is not supported. Package scanning deployment is not supported for such URIs.

8. 经过检查,发现是ehcache使用的jersey jar太旧了,于是到jersey官网下载 jersey1.8。
下载地址:https://jersey.java.net/download.html。
注意,jersey现在已经推出了2系列版本,这里为了与ehcache原有版本保持一致,下载的是1系列的最后的release版本:1.8。
删除ehcache war包中WEB-INF/lib目录下的jersey-core-1.1.5.jar和jersey-server-1.1.5.jar。
增加新下载的jersey-servlet-1.18.jar、jersey-server-1.18.jar、jersey-core-1.18.jar。

9. 重新打包 ehcache war,复制到[jboss_home]/standalone/deployments目录下,然后启动JBoss
在Console中会抛出异常:com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes.

10. 修改web.xml
(1)不使用resteasy,增加
<context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>resteasy.scan.resources</param-name>
    <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>resteasy.scan.providers</param-name>
    <param-value>false</param-value>
</context-param>

(2)注释两个init parameter
<init-param>
    <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
    <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
</init-param>    
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>net.sf.ehcache.server.rest.resources</param-value>
</init-param>

11. 重新打包 ehcache war,复制到[jboss_home]/standalone/deployments目录下,然后启动JBoss

这次Console没有抛出异常,访问http://localhost:8282/ehcache/rest/sampleCache2/,返回如下内容:
<cache>
<cacheConfiguration>
<clearOnFlush>true</clearOnFlush>
<diskAccessStripes>1</diskAccessStripes>
<diskExpiryThreadIntervalSeconds>120</diskExpiryThreadIntervalSeconds>
<diskPersistent>false</diskPersistent>
<diskSpoolBufferSizeMB>30</diskSpoolBufferSizeMB>
<diskStorePath>/var/folders/3w/hlhsjmns5m9g6xv6xqk2864h0000gn/T/</diskStorePath>
<eternal>true</eternal>
<loggingEnabled>false</loggingEnabled>
<maxElementsInMemory>1000</maxElementsInMemory>
<maxElementsOnDisk>0</maxElementsOnDisk>
<name>sampleCache2</name>
<overflowToDisk>false</overflowToDisk>
<statistics>true</statistics>
<timeToIdleSeconds>0</timeToIdleSeconds>
<timeToLiveSeconds>0</timeToLiveSeconds>
</cacheConfiguration>
<description>
[ name = sampleCache2 status = STATUS_ALIVE eternal = true overflowToDisk = false maxElementsInMemory = 1000 maxElementsOnDisk = 0 memoryStoreEvictionPolicy = FIFO timeToLiveSeconds = 0 timeToIdleSeconds = 0 diskPersistent = false diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: net.sf.ehcache.statistics.LiveCacheStatisticsWrapper hitCount = 0 memoryStoreHitCount = 0 diskStoreHitCount = 0 missCountNotFound = 0 missCountExpired = 0 size = 0 ]
</description>
<name>sampleCache2</name>
<statistics>
<averageGetTime>0.0</averageGetTime>
<cacheHits>0</cacheHits>
<diskStoreSize>0</diskStoreSize>
<evictionCount>0</evictionCount>
<inMemoryHits>0</inMemoryHits>
<memoryStoreSize>0</memoryStoreSize>
<misses>0</misses>
<onDiskHits>0</onDiskHits>
<size>0</size>
<statisticsAccuracy>STATISTICS_ACCURACY_BEST_EFFORT</statisticsAccuracy>
</statistics>
<uri>http://localhost:8282/ehcache/rest/sampleCache2/</uri>
</cache>

至此,说明ehcache部署成功!

参考文献:
1. http://stackoverflow.com/questions/7383146/javax-xml-ws-webserviceexception-unable-to-create-jaxbcontext
2. http://jiajun-kucoo.blog.163.com/blog/static/64148688201352634253468/
3. http://forums.terracotta.org/forums/posts/list/7295.page
4. https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7
5. https://access.redhat.com/site/solutions/107983
6. https://access.redhat.com/site/solutions/395293
7. https://community.jboss.org/thread/234965
8. https://access.redhat.com/site/solutions/97523
9. http://spring-java-ee.blogspot.in/2011/12/how-to-resolve-spring-data-neo4j-jersey.html

没有评论: