SugarCRM integration and Apache AxisThe most read articles here on beanizer.org are with no doubt those related to SugarCRM integration. Up to now our articles have focused on integrating with PHP, but following some readers’ request, starting from this article we’ll talk about integrating SugarCRM with Java. Though Java has strong and long lasting SOAP support, we’ve been asked for some kind of tutorial specific to Sugar. |
Apache Axis is an implementation of the SOAP (“Simple Object Access Protocol”) submission to W3C. It exists for Java and C++, we’re obviously going to use the first one. What we are particularly interested in is the class WSDL2Java (included in the distribution) which, given a wsdl file, is able to automatically build the corresponding classes for methods and data types. From now on I’ll take for granted the following assumptions about what we are using:
- JDK5 (or higher)
- SugarCRM 5
- Axis 1.4 (Java version)
After downloading and uncompressing the correct axis distribution, from a console “cd” into axis’ directory. You’ll see there’s a “lib” directory, containing all the jar files we need. Now we need to launch the class “WSDL2Java” with a reference to a valid sugar crm wsdl file. Given that your sugar crm installation is located at “http://localhost/sugarcrm” , the command line on Linux could be something like:
java -cp lib/axis.jar:lib/axis-ant.jar:lib/commons-discovery-0.2.jar:
lib/commons-logging-1.0.4.jar:lib/jaxrpc.jar:
lib/log4j-1.2.8.jar:lib/saaj.jar:lib/wsdl4j-1.5.1.jar
org.apache.axis.wsdl.WSDL2Java -o . -d Session -p org.beanizer.sugarcrm http://localhost/sugarcrm/soap.php?wsdl
The “-o” option will set the output directory, “-d” specifies how to deploy the server implementation (in this case “Session” means that a new instance of the implementation class will be created for each session) and “-p” defines the destination package to use. If everything goes fine, we will have on the current directory a new “org.beanizer.sugarcrm” package, containing a bunch of classes that represent our java SOAP interface to Sugar CRM. In our projects we will need this newly created package together with the jars contained in the “lib” directory to reside in our classpath.
First steps with Java / SugarCRM integration
In our classes don’t forget to import the needed packages:
import java.security.MessageDigest;
import org.beanizer.sugarcrm.*;
Let’s have a look at how to use the generated classes. First thing we will instantiate a “SugarsoapLocator” class, which will allow us to open a “port” object towards our SugarCRM.
Sugarsoap service=new SugarsoapLocator();
SugarsoapPortType port=service.getsugarsoapPort
(new java.net.URL("http://localhost/sugarcrm/soap.php"));
There are a few methods that don’t require us to be authenticated, so at this point we are already able to call them:
System.out.println(port.get_server_time());
System.out.println(port.get_server_version());
I guess their usage is quite obvious.
But for most methods we need to “login” to SugarCRM. To do this, we need a valid user and password. Note that the password must be MD5 encoded and in hexadecimal format. We’ll use the “MessageDigest” class included in java.security, and a custom method (see below) “getHexString” to convert the byte array result we get into hexadecimal. If the authentication succedes we’ll receive back a session id , which we’ll use for subsequent method calls, otherwise the session id will be “-1” and we’ll receive an error. Here is the code:
User_auth userAuth=new User_auth();
userAuth.setUser_name("myuser");
MessageDigest md =MessageDigest.getInstance("MD5");
String password=getHexString(md.digest("mypassword".getBytes()));
userAuth.setPassword(password);
userAuth.setVersion("0.1");
Set_entry_result loginRes=port.login(userAuth, "myAppName");
System.out.println("Error=" + loginRes.getError().getNumber());
String sessionID = loginRes.getId();
System.out.println("Session ID: " + sessionID);
Once we have a valid session id we can interact with SugarCRM. Let’s see how to query SugarCRM to get some account records. The parameters we pass to the “get_entry_list” method of our “port” object are:
- a session id
- a module name (“Accounts” in this case, but the method is generic so, to query for contacts, it would be “Contacts” and so on)
- a query (empty this time, but can be something like “name =’myname’ ” or anything else provided we use valid syntax, existing fields and the right value type)
- order by clause
- offset (numeric) , which record to start from
- a String array with the names of the fields to retrieve
- max number of records to retrieve
- if deleted records have to be retrieved (Sugar CRM doesn’t physically delete records, it just flags them as deleted)
Get_entry_list_result entryList=port.get_entry_list(sessionID,"Accounts","", "",0,
new String[]{"name","phone_office"}, 10, 0);
System.out.println(entryList.getError().getDescription());
for(Entry_value entry : entryList.getEntry_list()){
Name_value[] nvl=entry.getName_value_list();
System.out.println( nvl[0].getValue() + " - " + nvl[1].getValue());
}
We simply query for a list of entries, and then cycle through them to get the name/value couple of the requested fields (in this case just “name” and “phone_office”).
There’s a lot more to say about “get_entry_list”, but I think there’s enough meat for this session, so I’ll leave further explanations to the following articles.
The only thing left is the little method implemented to convert an array of bytes to an hexadecimal string. Here it is:
1: public String getHexString(byte[] data) throws Exception {
2: StringBuffer buf = new StringBuffer();
3: for (int i = 0; i < data.length; i++) {
4: int halfbyte = (data[i] >>> 4) & 0x0F;
5: int two_halfs = 0;
6: do {
7: if ((0 <= halfbyte) && (halfbyte <= 9))
8: buf.append((char) ('0' + halfbyte));
9: else
10: buf.append((char) ('a' + (halfbyte - 10)));
11: halfbyte = data[i] & 0x0F;
12: } while(two_halfs++ < 1);
13: }
14: return buf.toString();
15: }
Hasta la proxima.
Credits
1) Many thanks to Adam Wells for bug-fixing the code
2) The “getHexString” method code is taken from www.anyexample.com .