[
https://issues.apache.org/jira/browse/AXIS2-5792?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15360098#comment-15360098
]
Thorsten Schöning commented on AXIS2-5792:
------------------------------------------
Another test from me as well and EnableChildFirstClassLoading doesn't change a
thing on my Windows env, neither in axis2.xml nor services.xml, but it does and
solves the problem in my Ubuntu 14.04. At least for 1.7.3, 1.6.2 doesn't work
at all with that option enabled in my Ubuntu 14.04, while it does in my
Windows, but don't change a thing on the problem. So it seems that the
classloader implementations in the different envs/Java versions are deciding.
> Add a more strict service first class loader?
> ---------------------------------------------
>
> Key: AXIS2-5792
> URL: https://issues.apache.org/jira/browse/AXIS2-5792
> Project: Axis2
> Issue Type: Improvement
> Components: deployment
> Affects Versions: 1.6.3, 1.7.3
> Environment: Windows 8.1 x64 Prof., Tomcat 7.0.68, JDK 1.8.0_92 x64
> Reporter: Thorsten Schöning
> Attachments: AXIS2-5792 src 1.7.3.zip, AXIS2-5792 src.zip, Axis2_5792
> 1.7.3.zip, Axis2_5792.zip
>
>
> I have a web service based on Axis2 1.6.3 currently and Axis2 provides
> httpcore-4.0. In my service I want to use HttpCore 4.4.5 and HttpClient 4.5.2
> and both core packages provide the class BasicLineFormatter, but some classes
> new in HttpCore 4.4.5 need a newer version of that class than HttpCore 4.0
> can provide. This leads to exceptions like the following:
> {CODE}
> Caused by: java.lang.NoSuchFieldError: INSTANCE
> at
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:53)
> at
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:57)
> at
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:47)
> at
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:82)
> at
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:95)
> at
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:104)
> at
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:62)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:572)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:174)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:158)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:149)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:125)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:116)
> {CODE}
> {CODE}
> Caused by: java.lang.NoClassDefFoundError: Could not initialize class
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:572)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:174)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:158)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:149)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:125)
> at
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:116)
> {CODE}
> The problem is that when my service is about to be started, Axis2 used the
> BasicLineFormatter (indirectly) on its own already, loaded it and
> DeploymentClassLoader.loadClass finds that class in its own cache afterwards.
> This way the newer version of that class bundled with my service will never
> be used by default. Because the class is in the cache, using
> "EnableChildFirstClassLoading" doesn't change a thing here because the cache
> is always queried first.
> I could work around that problem by changing the class loader of my service
> in ServiceLifeCycle.startUp: The new class loader is just another instance of
> DeploymentClassLoader which I put all the URLs needed for Jars and classes
> and such into, use "EnableChildFirstClassLoading" by default and provide the
> already available class loader as the new parent:
> {CODE}
> class WsAxis2SvcCl extends DeploymentClassLoader
> [...]
> private static boolean shouldWrap(AxisService service)
> {
> String paramValue = (String)
> service.getParameterValue("EnableSvcFirstClassLoading");
> paramValue =
> StringUtils.defaultIfBlank(paramValue, "false");
> if (!JavaUtils.isTrueExplicitly(paramValue.trim()))
> {
> return false;
> }
> return true;
> }
> [...]
> protected WsAxis2SvcCl( Set<URL> urls,
> ClassLoader parent)
> {
> super(urls.toArray(new URL[urls.size()]), null, parent, true);
> }
> [...]
> static void wrapIf(AxisService service)
> {
> if (!WsAxis2SvcCl.shouldWrap(service))
> {
> return;
> }
> ClassLoader origCl = service.getClassLoader();
> Path svcDir = Axis2ServiceConf.getSvcDir(service);
> Set<URL> clUrls =
> ClNdClassLoaderUrlsProv.getUrlsRe(svcDir.toFile());
> ClassLoader newCl = new WsAxis2SvcCl(clUrls, origCl);
> service.setClassLoader(newCl);
> }
> {CODE}
> This way the classes and jars of my service are always considered first and
> only things not found in there are forwarded to the default Axis2 class
> loader used before. In the end, my classes using HttpCore 4.4.5 get their
> BasicLineFormatter and Axis2 keeps using its own. The "trick" is that
> DeploymentClassLoader.findLoadedClass only searches the current instance, no
> parent or such, and by providing a new instance I get a clean start for
> loading the service classes without interfering with the former already
> present Axis2 loader.
> As I understand DeploymentClassLoader, such problems can't be addressed
> without another classloader like mine, so I woudl like to suggest exactly
> such an approach like I implemented now to be added. As I did already, one
> could configure the use of that class loader on a per service level and would
> therefore don't introduce any problems with backwards compatibility. If
> interested, I could provide more of my implementation.
> Or is there any other approach I have missed to deal with same classes in
> incompatible versions like in my case?
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]