Licensing code conflicts with classloader

Hi
We’ve been building an extension to a third-party product using Aspose.Words. The functionality all works great, but when we try to install the license file, things go a little wrong.
Basically, you’ve done a great job of making sure that a) the license file is valid, and b) the licensing code hasn’t been tampered with (using a sealed jar, I believe). Unfortunately, the product we’re using has a custom class-loader (specifically, it loads jars out of a database rather than off the file system), and the licensing just doesn’t work - no matter what we try, the generated Word docs appear with the “unlicenced” header. We’ve tried several techniques to work around this, without success.

We can provide more technical details if required. However, the basic question is: is it possible for you to provide us with a licensing mechanism that works in a different way, to enable us to quickly and easily get our component integrated with Aspose.Words. Or something else that will help us to solve the problem?

Please cc your reply to htreisman-at-avoka.com

Many thanks,
Howard Treisman
CTO,
Avoka Technologies

Hi, Howard,
Yes, we will help you to solve the problem. Ours license scheme is simple enough and works well with many non-standard classloaders. If it doesn’t work with your classloader we obliged to resolve this.
First of all, please, try to load your license in standard environment to check are your license valid. What kind of license you are using: Aspose.Words or Aspose.Total?
About cc, please check in “Enable Email Notifications…” in your forum account settings.
Best Regards,

Hi
Our license is Aspose.Words. It’s definitely valid, because we CAN get everything to work when we put the Aspose jar file into the application server’s classpath - but we want to avoid doing that, and rather do the class-loading the “proper” way, which is to use the custom classloader.
David and Yuri, who have been working on this problem, may have more to add…
Howard

Hi,
Are license throws when you load it?
May be your classroader can’t load resources from the Aspose jar. Please try this:

InputStream stream = License.class.getResourceAsStream("/resources/Aspose.License.BlackList.xml");

Another option – it’s can be conflict between application server’s classloader and your custom classloader. Try to reboot your application server (or wipe out its buffers by any other way) – may be its classloader “remember” Aspose jar that was in its classpath.
Best Regards,

Hi Konstantin
Unfortunately it’s not a simple classloader issue. We can load resources fine from the jar with the classloader. ie. getResourceAsStream() works fine and we can load the license file itself as a resource without a hitch. The setLicense call fails further on when it trys to load the manifest file. The Adobe classloader is using a custom URL protocol ‘module:’ .Unfortunately the URL() constructor you are using to load the manifest file does not work with this protocol. I believe this is really a bug in the Adobe Classloader (I should know as I wrote the classloader for the Borland AppServer which also used a custom protocol and I had the exact same bug!) .
As far as I know it won’t be possible for you to work around this problem on your end without delegating to the classloader to load the manifest file ie to use getResourceAsStream, which presumably weakens your security model as the manifest could then be spoofed.
I’m not set up to reproduce the problem on this machine at the moment. I’ll try to post (or get my collegue Yuri to when he’s back later in the week) a full stack trace showing the problem so you can have a look at it.
…David
Avoka Technologies

Hi David,
We had a similar problem with Oracle OC4J classloader that uses ‘code-source:’ URL prefix. This classloader also had a bug (moreover the bug is fixed in last OC4J versions, as far as I know).
Anyway we embedded workaround in license loading logics for such classloader’s bugs. Apparently, Adobe classloader has another kind of this bug which we don’t fixed yetJ
Please, describe your environment: JVM, application server, Aspose.Words version. Code that loads license and stack trace (especially stack trace!) also needed.
As well you can try License.setLicense(InputStream) overload (if you don’t yet).
Best Regards,

Hi Konstantin,

We have JVM 1.5, JBoss,
Fragment of manifest:
Manifest-Version: 1.0
Specification-Title: Aspose.Words for Java
AssemblyProduct: Aspose.Words for Java
Implementation-Title: Aspose.Words for Java
Specification-Vendor: Aspose Pty Ltd
Specification-Version: 2.0.2.0
Implementation-Version: 2.0.2.0
AssemblyInformationalVersion: 2006.12.13
Our code:

ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader();
File tempFile = null;
try
{
    ClassLoader classLoader = WordManipulationService.class.getClassLoader();

    tempFile = File.createTempFile("avoka", "tmp");
    InputStream jarInputStream = classLoader.getResourceAsStream("/Aspose.Words.jdk15.jar");
    OutputStream fileOutputStream = new FileOutputStream(tempFile);
    bufferedStreamCopy(jarInputStream, fileOutputStream);
    fileOutputStream.close();
    jarInputStream.close();

    URL[] urls = new URL[] { tempFile.toURL() };
    URLClassLoader cl = new URLClassLoader(urls, classLoader);
    Thread.currentThread().setContextClassLoader(cl);
    InputStream licenseStream = cl.getResourceAsStream("/license/Aspose.Words.lic");

    Class licenseClass = Class.forName("com.aspose.words.License", true, cl);
    Object impl = licenseClass.newInstance();
    Class[] paramClasses = new Class[] { InputStream.class };
    Object[] paramValues = new Object[] { licenseStream };
    Method method = licenseClass.getMethod("setLicense", paramClasses);
    method.invoke(impl, paramValues);
    licenseStream.close();
} catch (Exception e)
{
    e.printStackTrace();
}
finally
{
    if (tempFile != null)
    {
        tempFile.delete();
    }
    Thread.currentThread().setContextClassLoader(oldClassloader);
}

Exception Stack Trace:

2008-05-08 16:51:50,826 INFO [STDOUT] at java.lang.Thread.run(Thread.java:595)
2008-05-08 16:51:50,826 INFO [STDOUT] Caused by: java.net.MalformedURLException: unknown protocol: module
2008-05-08 16:51:50,826 INFO [STDOUT] at java.net.URL.(URL.java:574)
2008-05-08 16:51:50,826 INFO [STDOUT] at java.net.URL.(URL.java:464)
2008-05-08 16:51:50,826 INFO [STDOUT] at java.net.URL.(URL.java:413)
2008-05-08 16:51:50,826 INFO [STDOUT] at com.aspose.words.ew.b(Unknown Source)
2008-05-08 16:51:50,826 INFO [STDOUT] at com.aspose.words.ew.a(Unknown Source)
2008-05-08 16:51:50,826 INFO [STDOUT] at com.aspose.words.License.setLicense(Unknown Source)
2008-05-08 16:51:50,826 INFO [STDOUT] … 101 more
2008-05-08 16:51:50,904 INFO [STDOUT] Evaluation license for product: [Word Manipulation]. Organization: [null]. Invocations remaining: [100], minutes remaining: [360]

Thanks,
Yura

Hi Yura,
You are using an aged version of Aspose.Words. Please try the last one: https://releases.aspose.com/words/net
Best Regards,

Hi Konstantin,

Thanks for the reply. With new libraries everything runs OK on JBoss, but we have problems running on WebSphere:

Our code is

ClassLoader classLoader = WordManipulationService.class.getClassLoader();

InputStream licenseStream = classLoader.getResourceAsStream("/license/Aspose.Words.lic");
com.aspose.words.License license = new com.aspose.words.License();

license.setLicense(licenseStream);
licenseStream.close();

The exception stack trace is:

[23/05/08 17:23:58:484 EST] 00000045 ExceptionUtil E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "doSupports" on bean "BeanId(LiveCycle8#adobe-dscf.jar#EjbTransactionCMTAdapter, null)". Exception data: java.lang.NoClassDefFoundError: com.sun.org.apache.xerces.internal.impl.dv.util.Base64
at com.aspose.words.ew.a(Unknown Source)
at com.aspose.words.ew.a(Unknown Source)
at com.aspose.words.ew.a(Unknown Source)
at com.aspose.words.License.setLicense(Unknown Source)
at com.avoka.livecycle.wordManipulation.WordManipulationService.(WordManipulationService.java:144)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:177)
at java.lang.Class.newInstancePrototype(Class.java:1274)
at java.lang.Class.newInstance(Class.java:1263)
at com.adobe.idp.dsc.component.impl.DefaultPOJOInvokerImpl.createNewPOJOInstance(DefaultPOJOInvokerImpl.java:224)
at com.adobe.idp.dsc.component.impl.DefaultPOJOInvokerImpl.invoke(DefaultPOJOInvokerImpl.java:128)
at com.adobe.idp.dsc.interceptor.impl.InvocationInterceptor.intercept(InvocationInterceptor.java:134)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.transaction.interceptor.TransactionInterceptor$1.doInTransaction(TransactionInterceptor.java:74)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EjbTransactionCMTAdapterBean.execute(EjbTransactionCMTAdapterBean.java:336)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EjbTransactionCMTAdapterBean.doSupports(EjbTransactionCMTAdapterBean.java:212)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EJSLocalStatelessEjbTransactionCMTAdapter_caf58c4f.doSupports(Unknown Source)
at com.adobe.idp.dsc.transaction.impl.ejb.EjbTransactionProvider.execute(EjbTransactionProvider.java:104)
at com.adobe.idp.dsc.transaction.interceptor.TransactionInterceptor.intercept(TransactionInterceptor.java:72)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.interceptor.impl.InvalidStateInterceptor.intercept(InvalidStateInterceptor.java:37)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.interceptor.impl.AuthorizationInterceptor.intercept(AuthorizationInterceptor.java:88)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.engine.impl.ServiceEngineImpl.invoke(ServiceEngineImpl.java:113)
at com.adobe.idp.dsc.routing.Router.routeRequest(Router.java:102)
at com.adobe.idp.dsc.provider.impl.base.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:88)
at com.adobe.idp.dsc.provider.impl.vm.VMMessageDispatcher.doSend(VMMessageDispatcher.java:210)
at com.adobe.idp.dsc.provider.impl.base.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:57)
at com.adobe.idp.dsc.clientsdk.ServiceClient.invoke(ServiceClient.java:208)
at com.adobe.workflow.engine.PEUtil.invokeAction(PEUtil.java:556)
at com.adobe.idp.workflow.dsc.invoker.WorkflowDSCInvoker.transientInvoke(WorkflowDSCInvoker.java:261)
at com.adobe.idp.workflow.dsc.invoker.WorkflowDSCInvoker.invoke(WorkflowDSCInvoker.java:98)
at com.adobe.idp.dsc.interceptor.impl.InvocationInterceptor.intercept(InvocationInterceptor.java:134)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.transaction.interceptor.TransactionInterceptor$1.doInTransaction(TransactionInterceptor.java:74)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EjbTransactionCMTAdapterBean.execute(EjbTransactionCMTAdapterBean.java:336)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EjbTransactionCMTAdapterBean.doRequiresNew(EjbTransactionCMTAdapterBean.java:282)
at com.adobe.idp.dsc.transaction.impl.ejb.adapter.EJSLocalStatelessEjbTransactionCMTAdapter_caf58c4f.doRequiresNew(Unknown Source)
at com.adobe.idp.dsc.transaction.impl.ejb.EjbTransactionProvider.execute(EjbTransactionProvider.java:143)
at com.adobe.idp.dsc.transaction.interceptor.TransactionInterceptor.intercept(TransactionInterceptor.java:72)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.interceptor.impl.InvalidStateInterceptor.intercept(InvalidStateInterceptor.java:37)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.interceptor.impl.AuthorizationInterceptor.intercept(AuthorizationInterceptor.java:88)
at com.adobe.idp.dsc.interceptor.impl.RequestInterceptorChainImpl.proceed(RequestInterceptorChainImpl.java:44)
at com.adobe.idp.dsc.engine.impl.ServiceEngineImpl.invoke(ServiceEngineImpl.java:113)
at com.adobe.idp.dsc.routing.Router.routeRequest(Router.java:102)
at com.adobe.idp.dsc.provider.impl.base.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:88)
at com.adobe.idp.dsc.provider.impl.vm.VMMessageDispatcher.doSend(VMMessageDispatcher.java:210)
at com.adobe.idp.dsc.provider.impl.base.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:57)
at com.adobe.idp.dsc.clientsdk.ServiceClient.invoke(ServiceClient.java:208)
at com.adobe.workflow.engine.PEUtil.invokeAction(PEUtil.java:556)
at com.adobe.workflow.engine.ProcessEngineBMTBean.continueBranchAtAction(ProcessEngineBMTBean.java:2898)
at com.adobe.workflow.engine.ProcessEngineBMTBean.asyncInvokeProcessCommand(ProcessEngineBMTBean.java:646)
at com.adobe.workflow.engine.EJSLocalStatelessadobe_ProcessEngineBMTEJB_7d3cbd67.asyncInvokeProcessCommand(Unknown Source)
at com.adobe.workflow.engine.ProcessCommandControllerBean.doOnMessage(ProcessCommandControllerBean.java:145)
at com.adobe.workflow.engine.ProcessCommandControllerBean.onMessage(ProcessCommandControllerBean.java:94)
at com.ibm.ejs.container.MessageEndpointHandler.invokeMdbMethod(MessageEndpointHandler.java:992)
at com.ibm.ejs.container.MessageEndpointHandler.invoke(MessageEndpointHandler.java:725)
at $Proxy0.onMessage(Unknown Source)
at com.ibm.ws.sib.api.jmsra.impl.JmsJcaEndpointInvokerImpl.invokeEndpoint(JmsJcaEndpointInvokerImpl.java:201)
at com.ibm.ws.sib.ra.inbound.impl.SibRaDispatcher.dispatch(SibRaDispatcher.java:708)
at com.ibm.ws.sib.ra.inbound.impl.SibRaSingleProcessListener$SibRaWork.run(SibRaSingleProcessListener.java:584)
at com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:418)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1469)

Hi Yura,
Current version of Aspose.Words for Java doesn’t use com.sun.org.apache.xerces.internal.impl.dv.util.Base64. So your WebSphere still loads an old version of Aspose.Words. Please check your WebSphere class paths, delete an old jars, clear caches, restart servlet container, etc.
Regards,

Hi Konstantin,

Thank you for your reply. Indeed we had an old Aspose library sitting in websphere. After I removed it setting license worked ok. But I discovered another problem:

when I run code on JBoss everything works, but running the same code on websphere throws NullPointerException:

[26/05/08 15:45:17:062 EST] 00000040 ExceptionUtil E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "doSupports" on bean "BeanId(LiveCycle8#adobe-dscf.jar#EjbTransactionCMTAdapter, null)". Exception data: java.lang.NullPointerException
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Paragraph.accept(Unknown Source)
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.HeaderFooter.accept(Unknown Source)
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Section.accept(Unknown Source)
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Document.accept(Unknown Source)
at com.aspose.words.co.a(Unknown Source)
at com.aspose.words.fy.g(Unknown Source)
at com.aspose.words.fn.f(Unknown Source)
at com.aspose.words.MailMerge.executeWithRegions(Unknown Source)
at com.avoka.livecycle.wordManipulation.WordManipulationService.mergeDataWithRegions(WordManipulationService.java:450)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method).

The code that we are using is attached as well as the word document template itself.

Regards,

Yura

Hi Yuriy,
I don’t see attachments you speaking about. Please reattach the files. It will be better if you shrink your code so I can quickly reproduce the problem without use of superfluous software (JBoss, WebSphere, etc.).
Best Regards,

Hi Konstantin,

Here is the document

The code

more code

and system log

The line in the code.txt that thows exception is

mailMerge.executeWithRegions(xmlMergeDataSource);

Regards,

Yura

Hi Yura,
Afraid, it’s too much info for one errorJ Moreover, I can’t reproduce your case since I really can’t emulate your environment and your data sources.
Please, shrink your code so it can be launched on bare java, without using of application servers, beans and external data sources. You can just hardcode your Map. Two-three rows will be enough.
Aspose.Words is just a component. If you get it work on “plain” java environment – it will work on virtually any application server.
By the way, I am not specialist on WebSphere logs, but I see several “Problem accessing document” and “Can’t find read-only file” exceptions in the log.
Regards,

Hi Konstantin,

I wrote a simple test that runs ok on sun’s JVM. When I run this test on IBM’s machine it fails:

C:\Documents and Settings\Administrator>java -version
java version “1.5.0”
Java™ 2 Runtime Environment, Standard Edition (build pwi32dev-20060511 (SR2))

IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows Server 2003 x86-32 j9vmwi322
3-20060504 (JIT enabled)
J9VM - 20060501_06428_lHdSMR
JIT - 20060428_1800_r8
GC - 20060501_AA)
JCL - 20060511a

C:\Documents and Settings\Administrator>java -jar MailMergeTest_fat.jar
@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@
getinputDocD:\temp\test.doc
@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@
fieldNames: street1 suburb state postcode firstName
fieldValues: street1_v suburb_v state_v postcode_v firstName_v
java.lang.RuntimeException: Problem processing merge
at Test.mergeDataWithDoc(Test.java:57)
at Test.main(Test.java:29)
Caused by: java.lang.NullPointerException
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Paragraph.accept(Unknown Source)
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Body.accept(Unknown Source)
at com.aspose.words.CompositeNode.acceptChildren(Unknown Source)
at com.aspose.words.Section.accept(Unknown Source)
at com.aspose.words.kj.a(Unknown Source)
at com.aspose.words.kj.lF(Unknown Source)
at com.aspose.words.kj.a(Unknown Source)
at com.aspose.words.MailMerge.execute(Unknown Source)
at com.aspose.words.MailMerge.execute(Unknown Source)
at Test.mergeDataWithDoc(Test.java:53)
… 1 more

I am attaching the document, called test.doc

attaching the test code, called Test.txt