function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
kevoharakevohara 

Calling Webservice Method from Java

Hi,

 

I did a lot of googling and I am struggling to find out how to call my custom webservice method from Java.  I have set up my project to use WSC and the partner WSDL.  I have downloaded the WSDL for my custom class containing the webservice but I'm not sure what to do with it or how to call it.  

 

Can someone walk me throught the steps?  For reference, I have this project set up in eclipse and I am able to connect to the API using the WSC and partner wsdl.  I just need to know how to incorporate the custom WSDL, and how to call my service.

cloudcodercloudcoder

Once you have your custom wsdl you can use any web service framework in Java to make use of it. What is your specific error/issue and hopefully I can help a little more

 

ZycZyc

Actually I have similar questions. I am trying to make the java sample work (QuickstartApiSample.java). When I try the command

java -classpath Lib/wsc-20.jar com.sforce.ws.tools.wsdlc wsdlfiles/enterprise.wsdl Lib/sforceenterprise.jar

I get errors such as

=======================

[WSC][wsdlc.run:312]Created temp dir: C:\Users\ISOFTS~1\AppData\Local\Temp\wsdlc
-temp-861264342730245357-dir
Exception in thread "main" com.sforce.ws.wsdl.WsdlParseException: Parse error: F
ound invalid XML. processing instruction can not have PITarget with reserveld xm
l name (position: START_DOCUMENT seen   <?xml ... @1:8)
        at com.sforce.ws.wsdl.WsdlParser.next(WsdlParser.java:93)
        at com.sforce.ws.wsdl.Definitions.read(Definitions.java:110)
        at com.sforce.ws.wsdl.WsdlFactory.create(WsdlFactory.java:68)
        at com.sforce.ws.tools.wsdlc.<init>(wsdlc.java:75)
        at com.sforce.ws.tools.wsdlc.run(wsdlc.java:312)
        at com.sforce.ws.tools.wsdlc.main(wsdlc.java:303)
Caused by: com.sforce.ws.ConnectionException: Found invalid XML. processing inst
ruction can not have PITarget with reserveld xml name (position: START_DOCUMENT
seen   <?xml ... @1:8)
        at com.sforce.ws.parser.XmlInputStream.next(XmlInputStream.java:137)
        at com.sforce.ws.wsdl.WsdlParser.next(WsdlParser.java:89)
        ... 5 more
Caused by: com.sforce.ws.parser.XmlPullParserException: processing instruction c
an not have PITarget with reserveld xml name (position: START_DOCUMENT seen   <?
xml ... @1:8)
        at com.sforce.ws.parser.MXParser.parsePI(MXParser.java:2427)
        at com.sforce.ws.parser.MXParser.parseProlog(MXParser.java:1433)
        at com.sforce.ws.parser.MXParser.nextImpl(MXParser.java:1382)
        at com.sforce.ws.parser.MXParser.next(MXParser.java:1085)
        at com.sforce.ws.parser.XmlInputStream.next(XmlInputStream.java:135)
        ... 6 more

C:\Sforce>

=======================

What did go wrong? This is the first action to build a sfdc client application. It should be a simple and straightforward step. How do I solve this problem?

 

Let me know if you need my wsdl file and how I can send it to you.

 

Thanks a lot.

 

Zhongyi

goabhigogoabhigo

Did you find any solution to this? Please share. I have been googling for past 3 hours !!

pkurapkura

What exactly are you trying to accomplish ? Were you able to get the session Id using the partner wsdl ? Which version of apache axis are you using ( I used 1.4) ?

goabhigogoabhigo

I have written a web service class in my sandbox. It has a method. I need to call that method in Java.

 

I was successful in logging in and updating, querying etc using enterprise WSDL. I used wsc-22. I have also generated .jar file of my custom web service. Just not getting how to call the method?

 

Please let me know what I am missing.

pkurapkura

I'm assuming you generated your .jar file for your custom webservice using axis 1.4. What classes do you've in your jar file ? Do you've any binding and locator classes in your custom webservice jar ? Can you try to accomplish this  (Below createAccount was the method defined in my custom webservice) ? I tried to do this using partner wsdl and not enterprise wsdl. I don't think that limits your ability but a thing to consider. I think you're missing the binding and locator classes that are required.

 

Can you try the same using partner wsdl or are you bound to use enterprise wsdl ?

 

For Ex:

     customWebServiceBinding.setHeader(new customWebServiceLocator().getServiceName().getNamespaceURI(), "SessionHeader",
                new SessionHeader(partnerConnection.getConfig().getSessionId()));

     customWebServiceBinding.createAccount(accountParameters);

Make sure  you've wsc-xx.jar, partner-xx.jar, partner-axis.jar (generated using axis and partner wsdl), customwebservice.jar (generated using wsdl2java and custom webservice wsdl). XX- refers to wsc version you're using.

goabhigogoabhigo

Thanks for the reply.

 

I created .jar file using 

java -classpath wsc-20.jar com.sforce.ws.tools.wsdlc enterprise.wsdl enterprise.jar (by referring http://wiki.developerforce.com/page/Introduction_to_the_Force.com_Web_Services_Connector). Did not use Axis.

 

Yes I am missing binding and locator classes. In the jar, it has added _element to my class method (insertOrUpdate_element).

pkurapkura

Can you try this ?

Make sure  you've wsc-xx.jar, partner-xx.jar, partner-axis.jar (generated using axis and partner wsdl), customwebservice.jar (generated using wsdl2java and custom webservice wsdl). XX- refers to wsc version you're using.

 

I think you've wsc-20.jar and enterprise.jar for (partner-xx.jar) out of the 4 required. What you are missing is enterprise-axis.jar and customwebservice.jar.

1) Use wsdl2java of apache axis 1.4 with enterprise-wsdl you downloaded from your instance and create something like enterprise-axis.jar

2) run wsdl2java for your custom webservice wsdl and create mywebservice.jar. Once you do this, you'll have binding and locator classes for your webservice. Then make a call using

For Ex:

     customWebServiceBinding.setHeader(new customWebServiceLocator().getServiceName().getNamespaceURI(), "SessionHeader",
                new SessionHeader(partnerConnection.getConfig().getSessionId())); -> here you use enterprise connection.

     customWebServiceBinding.createAccount(accountParameters); ->call your appropriate method.

 

Include all the 4 jars and see if this helps.

goabhigogoabhigo

I am using wsc-22.jar, and I have generated mywebservices.jar too.

 

I have read lots of docs today and most of them say about wsdl2java. Just not getting as to how it should be included. Once that is included I think I will call the method as you suggested.

 

Do you have any inputs on using wsdl2java in eclipse?

 

 

pkurapkura

wsdl2java is a tool part of apache axis project. There's some plugin in eclipse that you can leverage (works for newer verison of apache axis). I was using old version of apache axis and was running it through command prompt. You don't include wsdl2java in your project.You use wsdl2java to generate stubs that can be leveraged for your work. All you've to do is download apache axis library and run wsdl2java tool against your wsdl and enterprise wsdl that generates java stubs that you can use to call your webservice written in another language (apex in this context).

goabhigogoabhigo

Somehow I found out that 1.4 works fine (I know I am missing out some thing, but with such deadline no time for research) with some patches. After so many trial-and-error method, created cient stub using wsdl2java. But couldn't find Locater or Binding in it !!

goabhigogoabhigo

Really appreciate you for taking time to reply. Thanks.

 

There were some missing files (jars) in the plug-in, when searched others had written solution for it. So applied the patch. After that I was able to create the code generator class - output of which is stub class. I know I am missing something here. May be tomorrow with a fresh mind it can be solved.

 

If you have any suggestion on what could be the missing thing please let me know.

goabhigogoabhigo

Hi pkura, I was able to generate java code from WSDL using Axis2 1.7.0-SNAPSHOT. I have created separate packages and put the code generated from Code Generator.

 

Can you please assist me in writing the code which calls the web service method?

pkurapkura

What classes are generated from Axis with your webservice wsdl ? Do you've any locator or binding classes in your jar file ?

goabhigogoabhigo

Hhha, I am glad that you replied. I have read the documents, blogs. Every where guys are mentioning about binding, locator classes. But I am unable to find one :(

 

Here is the snapshot of the classes generated by Axis from my apex web service class. 

 

goabhigogoabhigo

Also, just to add leadtherace is the namespace in my developer org. And my web service class is very basic:

 

global class HelloWorldWS {

    webservice static String sayHelloWorld() {
        return 'Hello from SFDC';
    }
}

 

Please let me know if you find anything missing. With your help I am almost in verge of completing this. THanks again for the help.

pkurapkura

Can you post your wsdl (remove any company specific info you have in the wsdl) ? I didn't use apache axis2 but I might have some suggestions once I look into your wsdl. If you could, please copy/paste the code from HelloWorldWSServiceStub.java too.

goabhigogoabhigo

HelloWorldWS.wsdl is below:

<?xml version="1.0" encoding="UTF-8"?>
<!--
 Web Services API : leadtherace.HelloWorldWS
-->
<definitions targetNamespace="http://soap.sforce.com/schemas/class/leadtherace/HelloWorldWS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://soap.sforce.com/schemas/class/leadtherace/HelloWorldWS">
 <types>
  <xsd:schema elementFormDefault="qualified" targetNamespace="http://soap.sforce.com/schemas/class/leadtherace/HelloWorldWS">
   <xsd:element name="DebuggingInfo">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="debugLog" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:simpleType name="ID">
    <xsd:restriction base="xsd:string">
     <xsd:length value="18"/>
     <xsd:pattern value="[a-zA-Z0-9]{18}"/>
    </xsd:restriction>
   </xsd:simpleType>
   <xsd:simpleType name="LogCategory">
    <xsd:restriction base="xsd:string">
     <xsd:enumeration value="Db"/>
     <xsd:enumeration value="Workflow"/>
     <xsd:enumeration value="Validation"/>
     <xsd:enumeration value="Callout"/>
     <xsd:enumeration value="Apex_code"/>
     <xsd:enumeration value="Apex_profiling"/>
     <xsd:enumeration value="Visualforce"/>
     <xsd:enumeration value="System"/>
     <xsd:enumeration value="All"/>
    </xsd:restriction>
   </xsd:simpleType>
   <xsd:simpleType name="LogCategoryLevel">
    <xsd:restriction base="xsd:string">
     <xsd:enumeration value="Internal"/>
     <xsd:enumeration value="Finest"/>
     <xsd:enumeration value="Finer"/>
     <xsd:enumeration value="Fine"/>
     <xsd:enumeration value="Debug"/>
     <xsd:enumeration value="Info"/>
     <xsd:enumeration value="Warn"/>
     <xsd:enumeration value="Error"/>
    </xsd:restriction>
   </xsd:simpleType>
   <xsd:complexType name="LogInfo">
    <xsd:sequence>
     <xsd:element name="category" type="tns:LogCategory"/>
     <xsd:element name="level" type="tns:LogCategoryLevel"/>
    </xsd:sequence>
   </xsd:complexType>
   <xsd:simpleType name="LogType">
    <xsd:restriction base="xsd:string">
     <xsd:enumeration value="None"/>
     <xsd:enumeration value="Debugonly"/>
     <xsd:enumeration value="Db"/>
     <xsd:enumeration value="Profiling"/>
     <xsd:enumeration value="Callout"/>
     <xsd:enumeration value="Detail"/>
    </xsd:restriction>
   </xsd:simpleType>
   <xsd:element name="DebuggingHeader">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="categories" minOccurs="0" maxOccurs="unbounded" type="tns:LogInfo"/>
      <xsd:element name="debugLevel" type="tns:LogType"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="CallOptions">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="client" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="SessionHeader">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="sessionId" type="xsd:string"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="AllowFieldTruncationHeader">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="allowFieldTruncation" type="xsd:boolean"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="sayHelloWorld">
    <xsd:complexType>
     <xsd:sequence/>
    </xsd:complexType>
   </xsd:element>
   <xsd:element name="sayHelloWorldResponse">
    <xsd:complexType>
     <xsd:sequence>
      <xsd:element name="result" type="xsd:string" nillable="true"/>
     </xsd:sequence>
    </xsd:complexType>
   </xsd:element>
  </xsd:schema>
 </types>
 <!-- Message for the header parts -->
 <message name="Header">
  <part name="AllowFieldTruncationHeader" element="tns:AllowFieldTruncationHeader"/>
  <part name="CallOptions" element="tns:CallOptions"/>
  <part name="DebuggingHeader" element="tns:DebuggingHeader"/>
  <part name="DebuggingInfo" element="tns:DebuggingInfo"/>
  <part name="SessionHeader" element="tns:SessionHeader"/>
 </message>
 <!-- Operation Messages -->
 <message name="sayHelloWorldRequest">
  <part element="tns:sayHelloWorld" name="parameters"/>
 </message>
 <message name="sayHelloWorldResponse">
  <part element="tns:sayHelloWorldResponse" name="parameters"/>
 </message>
 <portType name="HelloWorldWSPortType">
  <operation name="sayHelloWorld">
   <input message="tns:sayHelloWorldRequest"/>
   <output message="tns:sayHelloWorldResponse"/>
  </operation>
 </portType>
 <binding name="HelloWorldWSBinding" type="tns:HelloWorldWSPortType">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
  <operation name="sayHelloWorld">
   <soap:operation soapAction=""/>
   <input>
    <soap:header use="literal" part="SessionHeader" message="tns:Header"/>
    <soap:header use="literal" part="CallOptions" message="tns:Header"/>
    <soap:header use="literal" part="DebuggingHeader" message="tns:Header"/>
    <soap:header use="literal" part="AllowFieldTruncationHeader" message="tns:Header"/>
    <soap:body use="literal" parts="parameters"/>
   </input>
   <output>
    <soap:header use="literal" part="DebuggingInfo" message="tns:Header"/>
    <soap:body use="literal"/>
   </output>
  </operation>
 </binding>
 <service name="HelloWorldWSService">
  <documentation></documentation>
  <port binding="tns:HelloWorldWSBinding" name="HelloWorldWS">
   <soap:address location="https://ap1-api.salesforce.com/services/Soap/class/leadtherace/HelloWorldWS"/>
  </port>
 </service>
</definitions>
goabhigogoabhigo

HelloWorldWSServiceStub.java

 

https://docs.google.com/open?id=0B7ImC5bbl_k8LXMyUW9ob0tSTG03a0RQajBRaU1Jdw

 

The code crosses 20,000 characters so have put in Google docs.

pkurapkura

Create a java test class with the following steps : (I haven't used axis 2 and don't have time now to generate these new classes).

1) Get the session Id using the enterprise wsdl

2) Create a SessionHeader instance with the above session Id.

3) Create a new HelloWorldWSServiceStub (see if you've any overloaded constructor that takes the session header element for this class)

4) See if the stub has a way to call sayHelloWorld method.

goabhigogoabhigo

Believe me, I have tried this before. But stub has strange parameters in sayHelloWorld:

 

public com.sforce.soap.schemas._class.leadtherace.helloworldws.SayHelloWorldResponse sayHelloWorld(

com.sforce.soap.schemas._class.leadtherace.helloworldws.SayHelloWorld sayHelloWorld50,com.sforce.soap.schemas._class.leadtherace.helloworldws.SessionHeader sessionHeader51,com.sforce.soap.schemas._class.leadtherace.helloworldws.CallOptions callOptions52,com.sforce.soap.schemas._class.leadtherace.helloworldws.DebuggingHeader debuggingHeader53,com.sforce.soap.schemas._class.leadtherace.helloworldws.AllowFieldTruncationHeader allowFieldTruncationHeader54)

throws java.rmi.RemoteException

{

.....

....

....

 

So when I try:

SessionHeader sh = new SessionHeader();
sh.setSessionId(config.getSessionId());
try {
HelloWorldWSServiceStub hw = new HelloWorldWSServiceStub();
hw.sayHelloWorld(sayHelloWorld50, sessionHeader51, callOptions52, debuggingHeader53, allowFieldTruncationHeader54);
} catch (AxisFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

 

Eclipse automatically fills the bolded text in sayHelloWorld call !!!

 

goabhigogoabhigo

After a lot more trouble shoot now I am able to get the response from Salesforce :) :) :) 

 

Below is the code:

private static void callHelloMethod() {
 String txt;
 try {
     config.setServiceEndpoint("https://ap1-api.salesforce.com/services/Soap/class/leadtherace/HelloWorldWS");
     SoapConnection sc = new SoapConnection(config);
     sc.setSessionHeader(config.getSessionId());
     txt = sc.sayHelloWorld();
     System.out.println("Value of txt: " + txt);
  }
  catch (ConnectionException e1) {
     System.out.println("ERROR in callHelloMethod " + e1.getMessage());
  }
}          

 Now the only thing bothering me is the hard coded Service End Point value. How do I get the value dynamically?

 

Thanks for all the help pkura.

pkurapkura

Congrats! I think there's a way to retrieve the endpoint from one of the classes generated by Axis (Not sure which one though - Good luck figuring it out).