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
MSchumacherMSchumacher 

Using compression with Java

Looking through the message boards I noticed a link to http://www.pocketsoap.com/weblog/2005/10/1565.html how to enable compression but being new to Java concepts, I am having some difficulties.
 
I added the code below to my eclipse project:
 public class SforceService extends SforceServiceLocator {
  public Call createCall() throws ServiceException {
   Call call = super.createCall();
   call.setProperty(HTTPConstants.MC_ACCEPT_GZIP, Boolean.TRUE);
   call.setProperty(HTTPConstants.MC_GZIP_REQUEST, Boolean.TRUE);
   return call;
  }
 } 
I have defined in my project:
 private Soap binding2 = null;
 
In the login routine I added:
    binding2 = new SforceService().getSoap();
    lr = binding2.login(userName, pwd); 
 
When I go to reset my url endpoint, I can't use _setproperty.  Of course when I attempt my first binding2.query(myQry) I receive the message

Destination URL not reset. The URL returned from login must be set in the SforceService

This makes sense.  Before I tried using compression, my code looked like the examples I downloaded:
    binding = (SoapBindingStub) new SforceServiceLocator()
      .getSoap();
    lr = binding.login(userName, pwd);
   binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY,
    lr.getServerUrl());
 
Simon Fells' web site also has a comment:
 
you have to configure axis to use the vastly superior CommonsHTTPSender class rather than the default HTTPSender class as its transport, this is done by changing the transport entry in the client-config.wsdd file from java:org.apache.axis.transport.http.HTTPSender to java:org.apache.axis.transport.http.CommonsHTTPSender
 
I don't understand how to do this in Eclipse.
 
Any assistance is greatly appreciated.  If you need more information, let me know.
 
Thanks.
Mike Schumacher

HarryKHarryK
Mike,

client-config.wsdd is a separate file that contains the paramaters referenced by Simon.
This is what mine looks like:

<?xml version="1.0" encoding="UTF-8"?>
<deployment name="commonsHTTPConfig"
    xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

  <transport name="http"  pivot="java:org.apache.axis.transport.http.CommonsHTTPSender" />
  <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender" />
  <transport name="java"  pivot="java:org.apache.axis.transport.java.JavaSender" />

</deployment>


In Eclipse, you provide this file as a VM argument (Run or Debug | Arguments) .
The format is:
-Daxis.ClientConfigFile= filename

I hope this helps,
Harry


HarryKHarryK
I have successfully implemented Simon's solution using Eclipse.  My problem is when I export the program as a -jar file from Eclipse and run it from the command line, there is NO compression. I can tell from the network traffic and also from the time it takes to run the job from the command line (about 10 times slower).
If I don't provide Eclipse with the client-config.wsdd file, the job runs just as long as from the command line.

The classpath looks the same. I provide the same -D parameter on the command line.
I am using Eclipse 3.1,  Axis 1.3, and Java 1.5.0_06.

I think I am missing something but don't know what that is.  Any help is appreciated.

Thanks in advance,
Harry



Message Edited by HarryK on 12-18-2006 11:05 AM

MSchumacherMSchumacher

I still receive the error below.

java.lang.NullPointerException

The errors occurs when lr=binding.login(userName, pwd).  userName and pwd have values so I assume it is the binding that is null.  I am not sure why.

 

   try {
    Soap binding = new SforceService().getSoap();
   } catch (ServiceException ex1) {
    System.out.println(ex1.getMessage());
    return;
   }

   try {
    lr = binding.login(userName, pwd);
   } catch (UnexpectedErrorFault ex2) {
    System.out.println(ex2.getExceptionMessage() + "\nUnexpected\n");
    return;
   } catch (LoginFault ex2) {
    System.out.println(ex2.getExceptionMessage() + "\nloginfault\n");
    return;
   } catch (RemoteException ex2) {
    System.out.println(ex2.getMessage() + "\nremote\n");
    return;
   }

Thanks Mike

Message Edited by MSchumacher on 12-18-2006 03:05 PM

SuperfellSuperfell
try {
     Soap binding = new SforceService().getSoap(); 
}


should be this, otherwise you're just creating a locally scoped variable called binding which goes out of scope straight away. (This is java stuff, nothing web services specific) 

try {
     binding = new SforceService().getSoap();
}
MSchumacherMSchumacher

This all started because I was trying to implement the compression from Simon Fell's website (http://www.pocketsoap.com/weblog/2005/10/1565.html) and just having difficulty getting it to work.  I added the

-Daxis.ClientConfigFile=xxxxclient-config.wsdd as a VM argument in Eclipse.

During the DoLogin() the loginresult (LR) is null.  Even if I put in an incorrect password, the lr=binding.loging() executes and no error is produced.   I know HarryK said he was able to get it to work, but I am still missing something.

Any ideas?

Thanks Mike

 

 

*******source code *********************************

package com.weiler.SpeedTest1;

import java.rmi.RemoteException;
import java.util.Date;

import javax.xml.rpc.Call;
import javax.xml.rpc.ServiceException;
import org.apache.axis.transport.http.HTTPConstants;

import com.sforce.soap.enterprise.ID;
import com.sforce.soap.enterprise.LoginResult;
import com.sforce.soap.enterprise.QueryResult;
import com.sforce.soap.enterprise.SforceServiceLocator;
import com.sforce.soap.enterprise.Soap;
import com.sforce.soap.enterprise.SoapBindingStub;
import com.sforce.soap.enterprise._SessionHeader;
import com.sforce.soap.enterprise.fault.LoginFault;
import com.sforce.soap.enterprise.fault.UnexpectedErrorFault;
import com.sforce.soap.enterprise.sobject.Account;
import com.sforce.soap.enterprise.sobject.SObject;


/**
 * @author mschumac
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class SpeedTest1 {
// private SoapBindingStub binding = null;
 private Soap binding = null;
 private LoginResult lr = null; //maintain the login results
    private LoginResult loginResult = null;
    private Account[] _accounts = null;
    private ID[] accounts = null;
    private Date date = null;
    private Date strDate = null;
    private Date endDate = null;
    private int cntAccts = 0;
    private String gAccountID = "";
    private String gAccountName = "";
    private String gAccountNumber = "";

 public static void main(String[] args) {
  new SpeedTest1();
 }
 public SpeedTest1() {
  //logon to salesforce.com
  System.out.println("Logging in to Salesforce.com.");
  doLogin();

  System.out.println("Retrieving Account Records.");
  VerifyAccount();
  System.out.println("Done Retrieving Account Records.");
    
 }
 
 public class SforceService extends SforceServiceLocator {
  public Call createCall() throws ServiceException {
   Call call = super.createCall();
   call.setProperty(HTTPConstants.MC_ACCEPT_GZIP, Boolean.TRUE);
   call.setProperty(HTTPConstants.MC_GZIP_REQUEST, Boolean.TRUE);
   return call;
  }
 } 
 
 private void VerifyAccount() {
  //check to see if we are already logged in
  if (lr == null) {
   System.out.println("Run the login sample before the others.\n");
   System.out.println("\n");
   return;
  }
  //create a variable to hold the query result
  QueryResult qr = null;
  //call the query saving the results in qr
  try {
   qr = binding
    .query("select Name, AccountNumber, Id, Type  from Account ");
  } catch (UnexpectedErrorFault uef) {
   System.out.println(uef.getExceptionMessage() + "\n\n");
   return;
  } catch (Exception e) {
   e.printStackTrace();
   System.out.println("\n\n");
   return;
  }
  //always a good idea
  if (qr.getSize() > 0) {
   SObject[] records = qr.getRecords();
   _accounts = new Account[records.length];
   //we can loop through the returned records
   for (int i = 0; i < records.length; i++) {
    //Because we asked for accounts we will convert
    //the SObject for each record into an Account object
    Account account = (Account) records[i];
    _accounts[i] = account;

    gAccountName = account.getName();
    gAccountNumber = account.getAccountNumber();

          //save the account ids in a class array
          if (accounts == null) {
              accounts = new ID[] {
                  account.getId()};
          }
          else {
              ID[] tempAccounts = null;
              tempAccounts = new ID[accounts.length + 1];
              for (int k = 0; k < accounts.length; k++) {
                tempAccounts[k] = accounts[k];
              }
              tempAccounts[accounts.length] = account.getId();
              accounts = tempAccounts;
          }
   
   }
//   System.out.println("");
  } else {
   System.out.println("Account not found!\n");
  }
 }  //end VerifyAccount()
 private void PrintDate(Date date) {
  System.out.println(date);
    
 } 

 private void doLogin() {
  String userName = "mschumac@weilerinc.com";
  String pwd = "xxxxxxxx";
  if (userName.length() == 0 || pwd.length() == 0)
   return;
  else {

   try {
    //binding = (SoapBindingStub) new SforceServiceLocator()
    //  .getSoap();
    binding = new SforceService().getSoap();
   } catch (ServiceException ex1) {
    System.out.println(ex1.getMessage());
    return;
   }

   try {
    lr = binding.login(userName, pwd);
   } catch (UnexpectedErrorFault ex2) {
    System.out.println(ex2.getExceptionMessage() + "\nUnexpected\n");
    return;
   } catch (LoginFault ex2) {
    System.out.println(ex2.getExceptionMessage() + "\nloginfault\n");
    return;
   } catch (RemoteException ex2) {
    System.out.println(ex2.getMessage() + "\nremote\n");
    return;
   }

   System.out.println("Login was successfull.");
/*
   System.out.print("The returned session id is: ");
   System.out.println(lr.getSessionId());
*/
   

   //on a successful login, you should always set up your session id
   //and the url for subsequent calls

   //reset the url endpoint property, this will cause subsequent calls
   //to made to the serverURL from the login result
   //binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY,
   //  lr.getServerUrl()); 
  
   //create a session head object
   _SessionHeader sh = new _SessionHeader();
   //set the sessionId property on the header object using
   //the value from the login result
   sh.setSessionId(lr.getSessionId());
   //add the header to the binding stub
            String sforceURI = new SforceServiceLocator().getServiceName().getNamespaceURI();
   //binding.setHeader(sforceURI, "SessionHeader", sh);   
   return;
  }
 }

}  // end class SpeedTest1

HarryKHarryK
It looks like you're using a different version of the API than I am.  I am using 7.0. Here is my Login which works fine:

  public SoapBindingStub binding;
  private SforceService service;
  private LoginResult lr;
  private static final String testURL= "https://test.salesforce.com/services/Soap/u/7.0";
  private static final String prodURL= "https://salesforce.com/services/Soap/u/7.0";

    public void login (String userName, String pwd, String env){
               
           try {
               service = new SforceService();
               if (env.length()> 0){
                  service.setSoapEndpointAddress(testURL);
               } else {
                   service.setSoapEndpointAddress(prodURL);
               }
               binding = (SoapBindingStub) service.getSoap();
           } catch (ServiceException ex1) {
               System.out.println("Service Exception logging on \n" + ex1.getMessage());
               return;
           }
           try {
               lr = binding.login(userName, pwd);
           } catch (UnexpectedErrorFault ex2) {
               System.out.println("unexpected login error \n" + ex2.getExceptionMessage() + "\n\n");
               return;
           } catch (LoginFault ex2) {
               System.out.println("login fault \n" + ex2.getExceptionMessage() + "\n\n");
               return;
           } catch (RemoteException ex2) {
               System.out.println("remote Exception \n" + ex2.getMessage() + "\n\n");
               return;
           }
   
                // on a successful login, you should always set up your session id
                // and the url for subsequent calls
   
                // reset the url endpoint property, this will cause subsequent calls
                // to made to the serverURL from the login result
   
                binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY, lr
                        .getServerUrl());
   
                // create a session head object
                SessionHeader sh = new SessionHeader();
                // set the sessionId property on the header object using
                // the value from the login result
                sh.setSessionId(lr.getSessionId());
                // add the header to the binding stub
                String sforceURI = new SforceServiceLocator().getServiceName()
                        .getNamespaceURI();
                binding.setHeader(sforceURI, "SessionHeader", sh);
   
                return;
            }

The SoapEndpointAddress is used for optionally logging to the sandbox account.


Simon -  Any ideas why running the -jar file from the command line will not compress the Soap message?  -Daxis.ClientConfigFile= ...  is the same file that runs within Eclipse which DOES compress the message.
Thanks,
Harry
MSchumacherMSchumacher
HarryK,
 
After tracking down a subtle syntax error that my untrained eye took a long time to notice, I thought I had it but I received the following error when lr=binding.login(username,pw).  I did update JDK to 1.5 and made sure my project was using the API 7.0.
 

java.lang.NoClassDefFoundError: org/apache/commons/codec/DecoderException

at org.apache.commons.httpclient.HttpMethodBase.<init>(HttpMethodBase.java:217)

at org.apache.commons.httpclient.methods.ExpectContinueMethod.<init>(ExpectContinueMethod.java:92)

at org.apache.commons.httpclient.methods.EntityEnclosingMethod.<init>(EntityEnclosingMethod.java:114)

at org.apache.commons.httpclient.methods.PostMethod.<init>(PostMethod.java:105)

at org.apache.axis.transport.http.CommonsHTTPSender.invoke(CommonsHTTPSender.java:153)

at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)

at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)

at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)

at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)

at org.apache.axis.client.Call.invokeEngine(Call.java:2784)

at org.apache.axis.client.Call.invoke(Call.java:2767)

at org.apache.axis.client.Call.invoke(Call.java:2443)

at org.apache.axis.client.Call.invoke(Call.java:2366)

at org.apache.axis.client.Call.invoke(Call.java:1812)

at com.sforce.soap.enterprise.SoapBindingStub.login(SoapBindingStub.java:1904)

at com.weiler.SpeedTest1.SpeedTest1.doLogin(SpeedTest1.java:149)

at com.weiler.SpeedTest1.SpeedTest1.<init>(SpeedTest1.java:57)

at com.weiler.SpeedTest1.SpeedTest1.main(SpeedTest1.java:48)

Exception in thread "main"

SuperfellSuperfell
The commons-codec jar is missing from your classpath.
HarryKHarryK
Any ideas why a jar file generated from Eclipse does NOT use compression? I have tried parameter  -Daxis.ClientConfigFile=client-config.wsdd  and also tried updating the system properties in the program:
        Properties props = System.getProperties();
        props.put("axis.ClientConfigFile", "client-config.wsdd");
        System.setProperties(props);

Running the program within Eclipse, compression works fine in both cases but neither method works running from a command line.

Thanks,
Harry
SuperfellSuperfell
I've seen problems in the past where classpath order can affect whether the app picks up your custom client-config, or the default one that's in the axis.jar.
MSchumacherMSchumacher

The commons codec jar file was my last missing link.    Thanks for the assistance from everyone.

HarryK:  if the order of the jar files in the classpath resovles your issue when running your jar file, please let me know.

Thanks.

Mike Schumacher

HarryKHarryK
Thanks Simon.  Unfortunately I don't have any good news to report.
I placed the wsdd file at the front of the classpath, I renamed the wsdd file to avoid name conflict, and even removed the wsdd file from axis.jar (temporarily). No luck.
I know the program looks for the wsdd file I provided because when I remove it from the directory, the program abends with a missing configuration file error message.
I am stuck and don't know what else to try. I am open to other ideas.

Thanks again,
Harry

SuperfellSuperfell
And you're sure the comand line version is referencing the same set of axis jars etc. ?
HarryKHarryK
Simon - You 're the man!!!!
The manifest was pointing to a different location for the classpath and by replacing the jar files in that location, the problem was solved.

Thanks again for sticking with it.

Harry