6 Replies Latest reply on Jan 26, 2005 2:49 PM by mette

    Problem with using custom datatypes in WSTypeMapping

    mette

      I am creating a document/literal web service, and I wish to use my own custom classes for the types used by the web service. I have therefore gone the path described in:

      http://www.jboss.org/wiki/Wiki.jsp?page=WSTypeMapping

      However, I am having a hard time getting it to work. Specifically, it seems JBoss cannot find my classes when the web service is deployed. I am getting a number of the following types of warnings:

      [exec] 09:56:46,845 WARN [TypeMappingDescription] Class not found: com.xyz.RegisterSensor

      however, at the end of it it tells me the web service was deployed.

      Then, when I go to the WS4EE page in JBoss, and click view the list of deployed web services, the page only displays "And now... Some Services", while in the log I see a stack trace:

      [exec] 10:09:03,374 DEBUG [ServiceEndpointServlet] doGet: http://localhost:8080/ws4ee/services
      [exec] 10:09:03,414 DEBUG [ServiceEndpointServlet] serviceName: null
      [exec] 10:09:03,414 DEBUG [ServiceEndpointServlet] Report available services
      [exec] 10:09:03,414 DEBUG [InvokerProvider] initServiceDesc: service=SensorRegistryServiceJSE
      [exec] 10:09:03,414 DEBUG [HandlerChainBaseImpl] Create a handler chain for roles: []
      [exec] 10:09:03,414 DEBUG [HandlerChainBaseImpl] init: [config=null]
      [exec] 10:09:03,645 ERROR [Engine] StandardWrapperValve[ServiceEndpointServlet]: Servlet.service() for servlet ServiceEndpointServlet threw exception
      [exec] java.lang.NoClassDefFoundError: com/xyz/RegisterSensor
      [exec] at java.lang.Class.getDeclaredMethods0(Native Method)
      [exec] at java.lang.Class.privateGetDeclaredMethods(Class.java:1647)
      [exec] at java.lang.Class.getDeclaredMethod(Class.java:1254)
      [exec] at org.apache.axis.description.ServiceDesc.loadServiceDescByIntrospection(ServiceDesc.java:938)
      [exec] at org.apache.axis.providers.java.JavaProvider.initServiceDesc(JavaProvider.java:730)
      [exec] at org.jboss.webservice.server.InvokerProvider.initServiceDesc(InvokerProvider.java:102)
      [exec] at org.apache.axis.handlers.soap.SOAPService.getInitializedServiceDesc(SOAPService.java:389)
      [exec] at org.apache.axis.deployment.wsdd.WSDDService.makeNewInstance(WSDDService.java:561)
      [exec] at org.apache.axis.deployment.wsdd.WSDDDeployment.getDeployedServices(WSDDDeployment.java:619)
      [exec] at org.apache.axis.configuration.FileProvider.getDeployedServices(FileProvider.java:358)
      [exec] at org.jboss.webservice.server.ServiceEndpointServlet.reportAvailableServices(ServiceEndpointServlet.java:184)
      [exec] at org.jboss.webservice.server.ServiceEndpointServlet.doGet(ServiceEndpointServlet.java:84)
      [exec] at javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
      [exec] at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:372)
      [exec] at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
      [exec] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
      [exec] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
      [exec] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
      [exec] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
      [exec] at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
      [exec] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
      [exec] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
      [exec] at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:157)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
      [exec] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
      [exec] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
      [exec] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
      [exec] at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:122)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
      [exec] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
      [exec] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
      [exec] at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
      [exec] at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
      [exec] at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
      [exec] at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
      [exec] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
      [exec] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
      [exec] at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
      [exec] at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
      [exec] at java.lang.Thread.run(Thread.java:534)

      The class in question, and all the other custom type classes I am getting warnings about during deployment are all located in a jar under WEB-INF/lib in my war, just like my JSE classes (which is located by JBoss), and I have checked and double checked the package class names, and they match. I even tried putting all the classes in question in the same jar as the one my JSE classes are in, but still to no avail. I am really stuck, as I cannot see what I am doing wrong. Please help!

        • 1. Re: Problem with using custom datatypes in WSTypeMapping
          thomas.diesler

          The classes should be seen by the deployment class loader. If WEB-INF/lib is not included it would be a bug.

          http://jira.jboss.com/jira/browse/JBWS-71

          Have you tried putting them in WEB-INF/classes ?

          • 2. Re: Problem with using custom datatypes in WSTypeMapping
            mette

            I tried copying the compiled class directory structure for the classes in question into WEB-INF/classes in my war. I redeployed, and double checked in the expanded war file in temp, and the classes were indeed in the right location. However, I still get the warning that the classes cannot be found on deploy, and the error when trying to load http://localhost:8080/ws4ee/services.

            I have double-checked the full class names again, and they are indeed identical.

            I would assume that someone has tested the custom classes, and that the failure must be caused by something more complex. Could it be because I am trying to create a document/literal web service, or because I am using a JSE and not an EJB service end point?

            • 3. Re: Problem with using custom datatypes in WSTypeMapping
              thomas.diesler

              Unlikely, I can look at it not earlier than next week.

              If you want to find out yourself you need to debug
              org.jboss.webservice.deployment.TypeMappingDescription

               /**
               * Load the javaType with the given class loader.
               */
               public Class loadJavaType(ClassLoader cl)
               {
               Class typeClass = null;
               String componentType = null;
               try
               {
               boolean isArrayType = javaType.endsWith("[]");
              
               if (isArrayType)
               componentType = javaType.substring(0, javaType.indexOf("["));
               else
               componentType = javaType;
              
              
               // Array classes do not exist in the wild. They only exist after loading the component
               // class type, and in 1.4.2 they are not created via the ClassLoader.loadClass call
               // http://developer.java.sun.com/developer/bugParade/bugs/4976356.html
               if (isArrayType)
               {
               if (JavaUtils.isJavaKeyword(componentType))
               {
               String className = JavaUtils.getLoadableClassName(javaType);
               typeClass = ClassLoader.getSystemClassLoader().loadClass(className);
               }
               else
               {
               // load the component first
               Class.forName(componentType, true, cl);
              
               String className = JavaUtils.getLoadableClassName(javaType);
               typeClass = Class.forName(className, true, cl);
               }
               }
              
               if (isArrayType == false)
               {
               if (JavaUtils.isJavaKeyword(javaType))
               {
               typeClass = getPrimitiveClass(javaType);
               }
               else
               {
               typeClass = cl.loadClass(javaType);
               }
               }
              
               // Now we got the class we can assign the serializer/deserializer
               initSerializerForClass(typeClass);
              
               }
               catch (ClassNotFoundException ignore)
               {
               log.warn("Class not found: " + javaType);
               }
               catch (NoClassDefFoundError ignore)
               {
               log.warn("No class definition for " + javaType);
               }
              
               return typeClass;
               }
              


              especially what URLs are associated with the given class loader.

              • 4. Re: Problem with using custom datatypes in WSTypeMapping

                Hi!

                I got rid of the warnings by specifying additional mappings in the jaxprc-mapping.xml file;

                <java-xml-type-mapping>
                 <java-type>my.class</java-type>
                 <root-type-qname>myprefix:mytypename</root-type-qname>
                 <qname-scope>element</qname-scope>
                </java-xml-type-mapping>
                


                dont know if this helps with the console error though.. let us know..

                good luck!

                regards/Ole

                • 5. Re: Problem with using custom datatypes in WSTypeMapping
                  mette

                  Ole, thank you for the reply.

                  I tried adding mappings for my two global elements, like you suggested, right after the package-mapping elements, as per the schema for the mapping file.

                  However, my warnings do not go away, nor does the console error.

                  I tried both having the classes in the jar and in the WEB-INF/classes directory.

                  • 6. Re: Problem with using custom datatypes in WSTypeMapping
                    mette

                    I figured out what the problem was myself. The classes mentioned in the warnings were indeed present in the war, and were not actually the problem. However, a jar that contained the superclasses of these classes, was not in the war file, and thus could not be loaded. When I added this jar to the war, the warnings went away, and the WS web page also displays fine. So I would say there is a bug with the error message, which can potentially be very confusing. I spent a fair amount of time staring at war content, comparing package names in detail and so on. When the classloader fails, it should look at what class it is actually failing in loading, which obviously is not happening.

                    Another interesting side-note is that once I added the jar, I actually ran into another problem, where my config files were specifying serializer/deserializer classes instead of the factories for the same. This caused exceptions to be thrown, and the web service not to deploy, whereas with the jar missing, the web service would deploy. That means the warnings somehow caused the deployment to skip parts of the deployment. thought you might be interested in this, as it may be another bug.