11 Replies Latest reply on Jan 30, 2009 9:01 AM by 843798

    Error while transforming XSLT by calling function with Reflection API

    843798
      Hi,

      I'm new to Reflection API. I want to call function from the jar file which is not in my application context. So I have loaded that jar ( say XXX.jar) file at runtime with URLClassLoader and call the function say [ *myTransform(Document document)* ]. Problem is that when I want to transform any XSLT file in that function it throws exception 'Could not compile stylesheet'. All required classes are in XXX.jar.

      If I call 'myTransform' function directly without reflection API then it transformation successfully completed.

      Following is code of reflection to invoke function
              ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
              URLClassLoader loader = new URLClassLoader(jarURLs, contextCL);
              Class c = loader.loadClass(fullClasspath);
      
              Constructor constructor = c.getDeclaredConstructor(constructorParamsClasses);
              Object instance = constructor.newInstance(constructorParams);
              Method method = c.getDeclaredMethod("myTransform", methodParamsClasses);
              Object object = method.invoke(instance, methodParams);
      Following is function to be called with reflection API.
      public Document myTransform ( Document document ) {
      // Reference of Document (DOM NODE) used to hold the result of transformation.
                  Document doc = null ;
                  // DocumentBuilderFactory instance which is used to initialize DocumentBuilder to create newDocumentBuilder.
                  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance () ;
                  // Reference of DocumentBuilder used to create new Document (DOM NODE).
                  DocumentBuilder builder;
                  try {
                        // Initialize DocumentBuilder by using DocumentBuilderFactory instance.
                        builder = factory.newDocumentBuilder ();
      
                        // Initialize new document instance by using DocumentBuilder instance.
                        doc = builder.newDocument () ;
      
                        // Creates new DOMSource by using document (DOM NODE) which is coming through current transform() method parameter.
                        DOMSource domsource = new DOMSource ( document ) ;
      
                        // Creates new instance of TransformerFactory.
                        TransformerFactory transformerfactory = TransformerFactory.newInstance () ;
      
                        // Creates new Transformer instance by using TransformerFactory which holds XSLT file.
                        Transformer transformer = null;
      
      /*
      *
      ********* exception is thrown from here onward ******************
      *
      */
                        transformer = transformerfactory.newTransformer (new StreamSource (xsltFile));
      
                        // Transform XSLT on document (DOM NODE) and store result in doc (DOM NODE).
                        transformer.transform ( domsource , new DOMResult ( doc ) ) ;
      
                  } catch (ParserConfigurationException ex) {
      
                        ex.printStackTrace();
                  } catch (TransformerConfigurationException ex) {
                        ex.printStackTrace();
      
      
                  } catch (TransformerException ex) {
      
                       ex.printStackTrace();
      
                  } catch (Exception ex) {
      
                       ex.printStackTrace();
      
                  }
                  //holds result of transformation.
                  return doc ;
      }
      Following is full exception stacktrace
      ERROR:  'The first argument to the non-static Java function 'myBeanMethod' is not a valid object reference.'
      FATAL ERROR:  'Could not compile stylesheet'
      javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
              at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:829)
              at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:623)
              at com.actl.dxchange.utilities.Transformation.transform(Transformation.java:83)
              at com.actl.dxchange.base.BaseConnector.transform(BaseConnector.java:330)
              at com.actl.dxchange.connectors.KuoniConnector.doRequestProcess(KuoniConnector.java:388)
              at com.actl.dxchange.connectors.KuoniConnector.hotelAvail(KuoniConnector.java:241)
              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:585)
              ...........
        • 1. Re: Error while transforming XSLT by calling function with Reflection API
          Alan.M
          Hi,
          method Object object = method.invoke(instance, methodParams);
          the methodParamsClasses can you show us how you set it
          the "methodParams" how you are setting it and sending it ? Can you check if this is an instance of Document and is not null


          Regards,
          Alan Mehio
          London,UK
          • 2. Re: Error while transforming XSLT by calling function with Reflection API
            843798
            Hi,
            Thanks for response.

            Following is code for setting 'methodParamsClasses' array object. I do ensure that Document is not null and valid. My application is web application.
            Document requestObj = /* my code for generating Document object*/
            Object[] methodParams = new Object[]{requestObj}
            Class[] methodParamsClasses = new Class[]{};
                        if (methodParams != null) {
                            methodParamsClasses = new Class[methodParams.length];
                            for (int i = 0; i < methodParams.length; i++) {
            
                                if (methodParams[i] instanceof Document) {
            /************** if parameter is instance of Document then I set class type as "Document.class" ***********/
                                    methodParamsClasses[i] = Document.class;
                                } else {
                                    methodParamsClasses[i] = methodParams.getClass();
            }
            }
            }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
            • 3. Re: Error while transforming XSLT by calling function with Reflection API
              EJP
              Class[] methodParamsClasses = new Class[]{};
              What's that for?
              if (methodParams != null) {
              How can it ever be null?
              methodParamsClasses = new Class[methodParams.length];
              Now you're getting somewhere. Get rid of the previous two lines and put Class[] in front of this one.
              for (int i = 0; i < methodParams.length; i++) {

              if (methodParams[i] instanceof Document) {
              /************** if parameter is instance of Document then I set class type as "Document.class" ***********/
              methodParamsClasses[i] = Document.class;
              } else {
              methodParamsClasses[i] = methodParams.getClass(); This is not necessarily correct. The same factors that made you write the code for Document.class apply for all the other parameters. In fact you know the method parameter classes at compile time, just write them in here as initializers for the array.
              • 4. Re: Error while transforming XSLT by calling function with Reflection API
                843798
                Hi,

                I have tried calling "myTransform" method by giving required parameter directly. Still getting same error as in first post.
                Following is the code I am using to call "myTransform" method.
                Document requestObj = /* my code for generating Document object*/
                Object[] methodParams = new Object[]{requestObj}
                Class[] methodParamsClasses = new Class[]{Document.class};
                
                ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
                URLClassLoader loader = new URLClassLoader(jarURLs, contextCL); /* jarURL is absolute path for XXX.jar*/
                Class c = loader.loadClass(fullClasspath);
                
                Constructor constructor = c.getDeclaredConstructor(constructorParamsClasses);
                Object instance = constructor.newInstance(constructorParams);
                Method method = c.getDeclaredMethod("myTransform", methodParamsClasses);
                Object object = method.invoke(instance, methodParams);
                During transformation of my XSLT document JVM needs to call some bean methods, and that bean class is in (let's say) XXX.jar. This XXX.jar is not in context of my web application. So I decided to call "myTransform" method(pls. refer 1st post for myTransform method ) with reflection API by providing currentContext and XXX.jar

                But still while transforming it does not find bean method which is actually in XXX.jar

                Or can u please suggest any other way so that Transformer can find required bean class from XXX.jar duruing transformation process.

                Regards,
                Rohit Lad

                Edited by: Rohit_Lad on Jan 28, 2009 7:31 PM

                Edited by: Rohit_Lad on Jan 29, 2009 3:30 PM
                • 5. Re: Error while transforming XSLT by calling function with Reflection API
                  843798
                  Does any one know how to do this

                  Edited by: Rohit_Lad on Jan 29, 2009 5:42 PM
                  • 6. Re: Error while transforming XSLT by calling function with Reflection API
                    DrClap
                    How to do it?

                    If it were me, I would just put that jar file into my application's context. Then you don't need superhuman workarounds to access it. It would just work. Problem solved.
                    • 7. Re: Error while transforming XSLT by calling function with Reflection API
                      843798
                      I wish I could do the same.
                      But problem is that, JAR file is not available to me at application deploy time.

                      Every time new jar file is uploaded through my web site and I need to use it in my transformation process.

                      Or can u please suggest any other way so that Transformer can find required bean class from XXX.jar at runtime duruing transformation process.

                      Following is part of XSLT which I am using.
                      <?xml version="1.0"?>
                      <xsl:stylesheet version="1.0" xmlns:aaa="mypackage.test.MyClass">
                           <xsl:template match="/responseData">
                                <xsl:for-each select="response">
                                     <XMLResponse>
                                          <xsl:for-each select="status">
                                               <xsl:variable name="Vvar_ResResponseType" select="."/>
                                               <xsl:attribute name="ResResponseType">
                                                    <xsl:value-of select="aaa:myBeanMethod($Vvar_ResResponseType)"/>
                                               </xsl:attribute>
                                          </xsl:for-each>
                                     </XMLResponse>
                                </xsl:for-each>
                           </xsl:template>
                      </xsl:stylesheet>
                      Thanks & Regards,
                      Rohit Lad
                      • 8. Re: Error while transforming XSLT by calling function with Reflection API
                        EJP
                        Or can u please suggest any other way so that Transformer can find required bean class from XXX.jar at runtime duruing transformation process.
                        Set the classloader that loads the JAR as the ContextClassLoader of the current Thread before calling the transform.

                        But you don't need to use Reflection to invoke the transform API at all, it's built in to Java.
                        • 9. Re: Error while transforming XSLT by calling function with Reflection API
                          843798
                          Thanks, It worked fine.

                          Following is modified code

                          ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
                          URLClassLoader loader = new URLClassLoader(jarURLs, contextCL);
                          {color:#0000ff}*Thread.currentThread().setContextClassLoader(loader);*{color}

                          Thanks & Regards,
                          Rohit Lad
                          • 10. Re: Error while transforming XSLT by calling function with Reflection API
                            843798
                            Thanks, It worked fine.

                            Following is modified code

                            ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
                            URLClassLoader loader = new URLClassLoader(jarURLs, contextCL);
                            {color:#0000ff}*Thread.currentThread().setContextClassLoader(loader);*{color}

                            Thanks & Regards,
                            Rohit Lad
                            • 11. Re: Error while transforming XSLT by calling function with Reflection API
                              843798
                              Thanks to all who spent their time to help me out