Announcement Announcement Module
Collapse
No announcement yet.
Consuming web services Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Consuming web services

    I am trying to consume a public web service using spring 2.5.6. I think my code matches the documented instructions, but blows up on initializing the service bean with:
    Code:
    java.lang.ExceptionInInitializerError
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emailValidateService' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is com.sun.xml.ws.model.RuntimeModelerException: A WebService annotation is not present on class: email.EmailValidateService
    My guess is that either the docs are out of sync with 2.5.6 (again!) or I am using the wrong class for the service and somehow giving Spring the impression that I have a stub from a service that I created (I did not, using a public service). My full code is below.

    Help!!!

    applicationContext.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
      - Spring Application Context
      -->
    
    <beans 
    	xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        					          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                            http://www.springframework.org/schema/util 
                            http://www.springframework.org/schema/util/spring-util-2.5.xsd">
    
      <bean id="emailValidateService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <property name="serviceInterface" value="email.EmailValidateService" />
        <property name="wsdlDocumentUrl"  value="http://www.webservicex.com/ValidateEmail.asmx?WSDL" />
        <property name="namespaceUri"     value="http://www.webservicex.net" />
        <property name="serviceName"      value="ValidateEmail" />
        <property name="portName"         value="ValidateEmailSoap" />
      </bean>
      
      <bean id="emailClient" class="email.EmailValidateClientImpl">
        <property name="emailValidateService" ref="emailValidateService" />
      </bean>
      
    </beans>
    EmailValidateService.java:
    Code:
    package email;
    
    public interface EmailValidateService {
      public boolean isValidEmail(String emailAddress); 
    }
    Test.java:
    Code:
    package email;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
      private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      private static EmailValidateService service = (EmailValidateService) context.getBean("emailValidateService");
    
      public static void main(String[] args) {
        try{
          System.out.println(service.isValidEmail("[email protected]"));
        }catch(Exception e) {
          e.printStackTrace();
        }
      }
    
    }

  • #2
    wsimport

    Even though you did not create the service, I think spring still requires you to have a valid service stub. This is necessary because several nuances exist in the exchange of messages between the client and the server. For example you've indicated that the web service you wish to invoke takes a string as it's parameter, but what if it took some complex object. The parameter type might be MyComplexType but the parameter itself might appear as part of a message whose message root is myComplexElement. This would be defined in the web services WSDL/schemas and is necessary information for sucessful messages exchange.

    I've taken the liberty of looking at the specific web service you listed, http://www.webservicex.com/ValidateEmail.asmx?WSDL, and if you actually read the WSDL/schema you'll see that what I said above post is actually very close to the truth. Your target webservice does not take string parameters, but IsValidEmail type parameters. Additionally it does not return a boolean, it returns a IsValidEmailResponse object. The interface you should have used is as follows

    Code:
    @WebService(name = "ValidateEmailSoap", targetNamespace = "http://www.webservicex.net")
    @XmlSeeAlso({
        ObjectFactory.class
    })
    public interface ValidateEmailSoap {
    
    
        /**
         * This method returns true or false for a given email address
         * 
         * @param email
         * @return
         *     returns boolean
         */
        @WebMethod(operationName = "IsValidEmail", action = "http://www.webservicex.net/IsValidEmail")
        @WebResult(name = "IsValidEmailResult", targetNamespace = "http://www.webservicex.net")
        @RequestWrapper(localName = "IsValidEmail", targetNamespace = "http://www.webservicex.net", className = "net.webservicex.IsValidEmail")
        @ResponseWrapper(localName = "IsValidEmailResponse", targetNamespace = "http://www.webservicex.net", className = "net.webservicex.IsValidEmailResponse")
        public boolean isValidEmail(
            @WebParam(name = "Email", targetNamespace = "http://www.webservicex.net")
            String email);
    
    }
    and can be generated using wsimport (Maybe others too, but I don't know them).

    Please note that the interface above requires other classes, which are also generated when you run wsimport on the provided wsdl.

    Comment


    • #3
      Thanks, I think I see my problem. Do I need to download Spring Web Services 1.5.6 and add its jar(s) separately?

      The Spring 2.5.6 documentation (section 17.5.8 - which I used as the model for my example) gives the impression that web service support is included (named JAX-WS in the docs) and makes no mention of wsimport.

      Spring docs seem to suffer from the "all you need to do is this" misdirection syndrome... and then you discover that there's a bunch of other things that you really need to do. I've hit this problem many times, only solved when I found a book or 3rd party tutorial that really explains what you need.

      Thanks for clarifying this.

      Comment


      • #4
        Looking at the spring 2.5.6 library, I don't see the packages which are necessary to facilitate web service consumption. This means that you'll like have to download the spring-ws libraries yourself if you want to use spring to consume the web services. I recommend using maven to bring in the dependencies, in which case you'll need to add the following to your pom file.

        Code:
            <dependency>
              <groupId>org.springframework.ws</groupId>
              <artifactId>spring-ws-core</artifactId>
              <version>1.5.0</version>
            </dependency>
            <dependency>
              <groupId>org.springframework.ws</groupId>
              <artifactId>spring-ws-core-tiger</artifactId>
              <version>1.5.0</version>
            </dependency>
        I haven't read the documentation you're referring to, but I am familiar with JAXWS and some of the way Spring works. I'll try to explain it as best I can, but again I'm still very new to spring.

        Basically, a web service is defined by a WSDL document and a schema (its contract). It is listening on at an IP address somewhere, using a specified port and a given URL mapping. The web service waits until it receives an XML message, and when it does it will begin to process that message by checking it against its contract and executing the prescribed operations. When it is done processing the message, it will respond to the sender using the mechanisms described in its contract. When you want to consume the web service you can construct an XML message which corresponds to the described contract and ship it off over http, however this is tedious and offers almost no benefits. This is where WSImport comes in.

        WSImport is a tool that is provided as part of the Metro libraries. In turn, the Metro libraries are a collection of JAXB and JAXWS libraries which facilitate the creation and consumption of web services. You can use WSImport to digest a WSDL and produce from it a set of Java classes which will automatically handle the marshalling to and from XML. These classes will coorespond to JAXWS and JAXB specifications and are not terribly difficult to use, but they do tie your application to the JAXWS specification. This is where spring comes in.

        Most of the time when you hear that Spring supports one technology or another, Spring actually provides some sort of interface to consume that technology. For example, Spring supports both JAXB and Castor marshalling through Spring-ws. As far as the Spring Endpoint is concerned it need only invoke its assigned marshaller when a message is received, and in turn the marshaller will provide result. The support for JAXB and Castor actually comes in the form of an implementation of that marshaller interface. This interface implementation is really just a wrapper to the JAXB or Castor objects, but it effectly provides a single interface from which all marshalling can be performed. Spring assumes that you're familiar with whichever technology you're going to use (JAXB/Castor) and leaves configuring the implementations internal objects to you. This means that unless you can provide the necessary information to configure your JAXWS Proxy object, you won't be able to use it.

        I hope this helps

        Comment


        • #5
          For anyone who might read this thread...

          In the end I did not need to download Spring Web Services to consume web services. Spring 2.5.6 supplied most of what I neeed.

          I found wsimport in my path (I am guessing from Java 6) and it generated the classes needed.

          I did need some additional JARs to satisfy dependencies. One was saaj-impl-1.3.2.jar. I believe there were other dependencies but they were satisfied by JARs that I already had in my classpath.

          I hope this helps the next person that hits this wall.

          Comment


          • #6
            I tried the same and still get the same exception

            Hi,

            I am newbie to Spring and trying to learn.
            I took the liberty to try executing your code in my local only for my concept understanding purpose.

            I did copied the same XML, Interface and Test class. Infact i set all spring jars in classpath along with Saaj 1.3.2 and commons logging jar.

            Also, i used the command in CMD prompt as:
            wsimport http://www.webservicex.com/ValidateEmail.asmx?WSDL
            for generating the WSDL classes.
            Also, set those classes in classpath.

            I am still getting the same Excetion you got. Can you please elaborrate as what were the steps that you carried forward for this?

            Thanks in advance!!

            Jai

            Comment


            • #7
              Pls guide me

              I am not sure as where I am making mistake. I request you all to please guide me, so that I can build good spring web service application.

              Can anybody give me a sample all spring application which consumes webservice, as similar to this posting; if possible? Also i request group to provide me a link for sample webservice application using Spring webservices too.

              Thank you much in advance!

              Jai

              Comment


              • #8
                Jai,

                In this thread dew_the_fifth has described one method for consuming web services.

                Spring WS provides a mforore elegant approach for consuming web services with WebServiceTemplate. It's elegant, but tricky - I am battling a couple of issues with it.

                Regarding tutorials for Spring WS, see: http://static.springsource.org/sprin...tml/index.html

                If you download Spring WS, you will find a few sample apps packaged in the zip file. See the samples dir in the zipped archive.

                Hope this helps.

                Comment


                • #9
                  Thanks for reply jegadesh. I will definitely look into that and will try Spring WS for sure.

                  Comment


                  • #10
                    Some problem!

                    Hello everybody! I have one problem. I tried to Jobs autowire the helper class but when I run the application on tomcat I get the following error:The Stellenmarkt prefix "context" for element "context:component-scan" is not bound. Do you have any clue?
                    For the record: everything else works fine (meaning Stellenangebote that without the helper I can run the helloworld webservice).

                    Comment


                    • #11
                      Originally posted by SmokeMaxxx View Post
                      Hello everybody! I have one problem. I tried to Jobs autowire the helper class but when I run the application on tomcat I get the following error:The Stellenmarkt prefix "context" for element "context:component-scan" is not bound. Do you have any clue?
                      For the record: everything else works fine (meaning Stellenangebote that without the helper I can run the helloworld webservice).
                      You are probably missing the schema definition (xmlns:context, xsi:schemaLocation) in your context file <beans> tag.

                      Comment


                      • #12
                        wsimport problem? 'WebService annotation is not present on class'

                        Originally posted by bmelloni View Post
                        For anyone who might read this thread...

                        In the end I did not need to download Spring Web Services to consume web services. Spring 2.5.6 supplied most of what I neeed.

                        I found wsimport in my path (I am guessing from Java 6) and it generated the classes needed.

                        I did need some additional JARs to satisfy dependencies. One was saaj-impl-1.3.2.jar. I believe there were other dependencies but they were satisfied by JARs that I already had in my classpath.

                        I hope this helps the next person that hits this wall.
                        Hi,

                        I experience the same problem. Using the same webservice as in the head of this topic...:

                        I would like to access the Webservice from a Spring-managed bean like this:
                        Code:
                          @WebServiceRef(wsdlLocation=" http://www.webservicex.com/ValidateEmail.asmx?WSDL")
                          private ValidateEmail service;
                        I imported the wsdl:
                        Code:
                        wsimport  -target 2.1 -p com.ws -s src/main/java/ -extension -Xnocompile  http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        During deployment I receive this exception:
                        Code:
                        ERROR - ContextLoader.initWebApplicationContext(220) | Context initialization failed
                        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emailDao': Injection of resource dependencies failed; nested exception is com.sun.xml.internal.ws.model.RuntimeModelerException: A WebService annotation is not present on class: com.ws.ValidateEmail
                        	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:300)
                        ...
                        Caused by: com.sun.xml.internal.ws.model.RuntimeModelerException: A WebService annotation is not present on class: com.ws.ValidateEmail
                        	at com.sun.xml.internal.ws.model.RuntimeModeler.getPortTypeName(Unknown Source)
                        I checked the generated class, and it really lacks the @WebService annotation and starts like this:
                        Code:
                          @WebServiceClient(name = "ValidateEmail", targetNamespace = "http://www.webservicex.net", wsdlLocation = "http://www.webservicex.com/ValidateEmail.asmx?WSDL")
                        public class ValidateEmail
                            extends Service
                        I received during wsimporting a number of warnings...:
                        Code:
                        parsing WSDL...
                        
                        
                        [WARNING] SOAP port "ValidateEmailSoap12": uses a non-standard SOAP 1.2 binding.
                        
                          line 113 of http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        
                        [WARNING] port "ValidateEmailHttpGet" is not a SOAP port, it has no soap:address
                        
                          line 116 of http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        
                        [WARNING] port "ValidateEmailHttpGet": not a standard SOAP port. The generated a
                        rtifacts may not work with JAXWS runtime.
                          line 116 of http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        
                        [WARNING] port "ValidateEmailHttpPost" is not a SOAP port, it has no soap:addres
                        s
                          line 119 of http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        
                        [WARNING] port "ValidateEmailHttpPost": not a standard SOAP port. The generated
                        artifacts may not work with JAXWS runtime.
                          line 119 of http://www.webservicex.com/ValidateEmail.asmx?WSDL
                        
                        generating code...
                        If I use ValidateEmailSoap, I receive:
                        Code:
                        @WebServiceRef(wsdlLocation=" http://www.webservicex.com/ValidateEmail.asmx?WSDL", type=ValidateEmail.class)
                        private ValidateEmailSoap service;
                        Code:
                        Caused by: java.lang.IllegalStateException: Specified field type [interface com.ws.ValidateEmailSoap] is incompatible with resource type [com.ws.ValidateEmail]
                        I use JDK 1.6.0_21 with JAX-WS RI 2.1.6 and Spring 3.0.3.RELEASE.
                        Any hints what could be the solution here?

                        br.:
                        Richi
                        Last edited by firesign; Nov 28th, 2010, 03:29 PM.

                        Comment


                        • #13
                          OK,

                          this is the right combination:

                          Code:
                          @WebServiceRef(ValidateEmail.class)
                          private ValidateEmailSoap service;

                          Comment


                          • #14
                            An addition to my original post:

                            Even though I was successful, I tried several other ways to write and call web services.

                            In the end I found that the simplest and cleanest is Apache CXF, using the code-first approach:
                            • To write a service, you simply write a java bean, then you expose it through pretty simple configuration in your spring context.
                            • To call a service, again you just do some configuration in your spring context, then load the auto-generated bean that proxies the call to the web service.
                            • So basically writing and calling is done through POJOs. And the configuration is all in the Spring Context, plus adding the necessary libraries.

                            You almost don't have to worry about the fact that it is a web service.

                            Comment


                            • #15
                              Hi,

                              thanks for your suggestion!

                              Upon your post I tried Apache CXF, and found cool (surprises, that it is documented well enough).
                              I have also found decent Maven plugins for WSDL->Java and XSD->Java inside, which I was longing for a while...

                              regards
                              R.

                              Comment

                              Working...
                              X