locked
Connect to web service with Java RRS feed

  • Question

  •  

    Hello,

     

    Has anyone tried to consume an MS CRM 4 webservice via Java?  We are trying to connect to the /MSCrmServices/2007/CrmService.asmx page and we receive error 401s.  The IIS log file shows this:

     

    2008-09-25 17:51:59 W3SVC1 192.168.250.55 POST /MSCrmServices/2007/CrmService.asmx - 80 mydomain\myusername 192.168.250.1 Java/1.6.0_07 401 5 64

     

    I know that if I open the web service page with a browser I get a 302 which is a redirect:

     

    2008-09-25 17:55:25 W3SVC1 192.168.250.55 GET /MSCrmServices/2007/CrmService.asmx - 80 mydomain\myusername 192.168.250.1 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+5.1;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+MS-RTC+LM+8) 302 0 0

     

    Has anyone successfully sent user credentials to CRM?

     

    TIA.

    Thursday, September 25, 2008 6:09 PM

Answers

  •  I ve succesfully connected to CRM Dynamics 4.0 Web Service using Axis2 (Soap1.2, NTLM Auth) and did a retrieveMultiple

    My code::

     

    .....  
    //you ll need this..  
    import com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken;  
    .......  
     
     
    public class TestCRM {  
     
    private static String endpointURL = "http://server:port/MSCrmServices/2007/CrmService.asmx";  
    private static String userName = "username";  
    private static String password = "password";  
    private static String host = "server";  
    private static int portport = port;  
     
    //To make sure you are using the correct domain open ie and try to reach the service. The same domain you entered there is needed here  
    private static String domain = "DOMAIN";   
     
    private static String orgName = "THIS_IS_REQUIRED"; //this does the work....  
       
        
    public static void main(String[] args) {  
        
        CrmServiceStub stub;  
        try {  
            stub = new CrmServiceStub(endpointURL);  
            setOptions(stub._getServiceClient().getOptions());  
             
            RetrieveMultipleDocument rmd = RetrieveMultipleDocument.Factory.newInstance();  
            RetrieveMultiple rm = RetrieveMultiple.Factory.newInstance();  
         
            QueryExpression query = QueryExpression.Factory.newInstance();  
            query.setColumnSet(AllColumns.Factory.newInstance());  
            query.setEntityName(EntityName.######.toString());  
            //query.setFilter...  
         
            rm.setQuery(query);  
            rmd.setRetrieveMultiple(rm);  
         
            //Now this is required. Without it all i got was 401s errors  
            CrmAuthenticationTokenDocument catd = CrmAuthenticationTokenDocument.Factory.newInstance();  
            CrmAuthenticationToken token = CrmAuthenticationToken.Factory.newInstance();  
            token.setAuthenticationType(0);     
            token.setOrganizationName(orgName);  
            catd.setCrmAuthenticationToken(token);  
         
            boolean fetchNext = true;  
            while(fetchNext){  
                RetrieveMultipleResponseDocument rmrd = stub.RetrieveMultiple(rmd,  catd, null, null);  
                RetrieveMultipleResponse rmr = rmrd.getRetrieveMultipleResponse();  
                BusinessEntityCollection bec = rmr.getRetrieveMultipleResult();  
          
                String pagingCookie = bec.getPagingCookie();  
                fetchNext = bec.getMoreRecords();  
          
                ArrayOfBusinessEntity aobe = bec.getBusinessEntities();  
                BusinessEntity[] myEntitiesAtLast = aobe.getBusinessEntityArray();  
          
                for(int i=0; i<myEntitiesAtLast.length; i++){  
                    //cast to whatever you asked for...  
                    ### myEntity = (###) myEntitiesAtLast[i];  
                }  
            }  
        }   
        catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
        
    private static void setOptions(Options options){  
        HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();  
          
        List authSchemes = new ArrayList();  
        authSchemes.add(HttpTransportProperties.Authenticator.NTLM);   
        auth.setAuthSchemes(authSchemes);   
         
        auth.setUsername(userName);  
        auth.setPassword(password);  
        auth.setHost(host);  
        auth.setPort(port);  
        auth.setDomain(domain);  
        auth.setPreemptiveAuthentication(false); //it doesnt matter...  
        options.setProperty(HTTPConstants.AUTHENTICATE, auth);  
        options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true"); //i think this is good.. not required though  




    Take a look here http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.crm.developer&tid=61c3fde8-259b-49ea-b42e-b7fa26109f61&cat=&lang=&cr=&sloc=&p=1
    This led me to that solution.

    Hope i helped

    Monday, February 2, 2009 9:39 AM

All replies

  • I've not tried connecting with Java, but I have tried connecting with .Net techniques from outwith the domain on which the CRM server resides, and got much the same results as you're describing above. Is your Java app attempting to connect with the Web Services as a user on a domain that is different from the CRM Server's domain?

    Wednesday, October 1, 2008 10:29 AM
  • I have done some more tests and determined that we had two issues.

     

    The first is our authentication method.  We had to use the Java security libraries to communicate with the web server using SPNEGO authentication. 

     

    The second problem was with our SOAP request.  This problem was very hard to nail down but we were using a sample SOAP message from CRM 4 Unleashed.  When we posted this message to the crmservice.asmx page we kept receiving an error 500 error.  Eventually we used a .NET application we wrote to create a contact using the web service.  I setup a packet sniffer on the CRM server and monitored the actual message sent.  It turns out that CRM 4 Unleashed did not provide a valid SOAP message for CRM.  When I took the message I obtained from the packet sniff and sent it to the server the contact was created. 

     

    Anyways this was a heck of a problem.  Microsoft and book writers should do a better job explaining the proper SOAP message format as well as provide more information on how to connect to the web services with non-.NET clients.  Web services are *supposed* to be client neutral.

    Thursday, October 2, 2008 3:04 PM
  •  

    You receive these errors, because you are not using an NTLM authentication mode. In order to connect to CRM web services from Java, look for Axis2 framework (http://ws.apache.org/axis2/) that supports the NTLM authentication and then in your Java code, provide your credentials:

     

    HttpTransportProperties.NTLMAuthentication ntlmAuthentication = new HttpTransportProperties().new NTLMAuthentication();
    ntlmAuthentication.setUsername("USER");
    ntlmAuthentication.setPassword("PASSWORD");
    ntlmAuthentication.setHost("HOST");
    ntlmAuthentication.setPort(PORT);
    ntlmAuthentication.setRealm("REALM");
               

    I hope that helps,

    Kuba

    Wednesday, October 8, 2008 2:13 PM
  • Yes, one of the problems was due to NTLM authentication but I fixed this as stated in my previous post.  I am using Sun's security library to connect to IIS.  The second problem was with the format of the SOAP request.  CRM Unleashed was incorrect in their example.

     

    Wednesday, October 8, 2008 2:39 PM
  • Is there any way to access MS CRM WS via JAX-WS rather then via Axis2? I generated WS stubs in NetBeans using JAX-WS style. When I'm trying to access CRM web service i'm getting next error:

    com.sun.xml.ws.client.ClientTransportException: request requires HTTP authentication: Unauthorized

    see my code below:

    CrmService service = new CrmService();
    CrmServiceSoap port = service.getCrmServiceSoap12();
    java.net.Authenticator.setDefault(new MyAuthenticator("user@company.com", "pwd"));
    WSBindingProvider bp = (WSBindingProvider) port;
    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://oursite/MSCrmServices/2007/CrmService.asmx");
    Retrieve parameters = new Retrieve();
    RetrieveResponse result = port.retrieve(parameters);

    class MyAuthenticator
          extends java.net.Authenticator
      {
        String user;
        String password;

        public MyAuthenticator(String user, String password)
        {
          this.user = user;
          this.password = password;
        }

        @Override
        protected java.net.PasswordAuthentication getPasswordAuthentication()
        {
          return new java.net.PasswordAuthentication(user, password.toCharArray());
        }
      }

    Plese, help me, what I'm doing wrong
    Thanks in advance

    Tuesday, November 18, 2008 7:14 PM
  • Probably just your authentication method.  You can try changing the CRM security to Basic just to verify this.

     

    Wednesday, November 19, 2008 1:56 PM
  • How and where can I change the CRM security to Basic on MS Dynamics CRM Online?
    Wednesday, November 19, 2008 4:52 PM
  • Sorry I didnt realize you were using CRM Online.  You should find out what kind of authentication CRM Online uses (probably spnego) and then use the correct java security library.  Look at my posts at the top of this thread for more info.

     

    Thursday, November 20, 2008 2:26 PM
  •  I ve succesfully connected to CRM Dynamics 4.0 Web Service using Axis2 (Soap1.2, NTLM Auth) and did a retrieveMultiple

    My code::

     

    .....  
    //you ll need this..  
    import com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken;  
    .......  
     
     
    public class TestCRM {  
     
    private static String endpointURL = "http://server:port/MSCrmServices/2007/CrmService.asmx";  
    private static String userName = "username";  
    private static String password = "password";  
    private static String host = "server";  
    private static int portport = port;  
     
    //To make sure you are using the correct domain open ie and try to reach the service. The same domain you entered there is needed here  
    private static String domain = "DOMAIN";   
     
    private static String orgName = "THIS_IS_REQUIRED"; //this does the work....  
       
        
    public static void main(String[] args) {  
        
        CrmServiceStub stub;  
        try {  
            stub = new CrmServiceStub(endpointURL);  
            setOptions(stub._getServiceClient().getOptions());  
             
            RetrieveMultipleDocument rmd = RetrieveMultipleDocument.Factory.newInstance();  
            RetrieveMultiple rm = RetrieveMultiple.Factory.newInstance();  
         
            QueryExpression query = QueryExpression.Factory.newInstance();  
            query.setColumnSet(AllColumns.Factory.newInstance());  
            query.setEntityName(EntityName.######.toString());  
            //query.setFilter...  
         
            rm.setQuery(query);  
            rmd.setRetrieveMultiple(rm);  
         
            //Now this is required. Without it all i got was 401s errors  
            CrmAuthenticationTokenDocument catd = CrmAuthenticationTokenDocument.Factory.newInstance();  
            CrmAuthenticationToken token = CrmAuthenticationToken.Factory.newInstance();  
            token.setAuthenticationType(0);     
            token.setOrganizationName(orgName);  
            catd.setCrmAuthenticationToken(token);  
         
            boolean fetchNext = true;  
            while(fetchNext){  
                RetrieveMultipleResponseDocument rmrd = stub.RetrieveMultiple(rmd,  catd, null, null);  
                RetrieveMultipleResponse rmr = rmrd.getRetrieveMultipleResponse();  
                BusinessEntityCollection bec = rmr.getRetrieveMultipleResult();  
          
                String pagingCookie = bec.getPagingCookie();  
                fetchNext = bec.getMoreRecords();  
          
                ArrayOfBusinessEntity aobe = bec.getBusinessEntities();  
                BusinessEntity[] myEntitiesAtLast = aobe.getBusinessEntityArray();  
          
                for(int i=0; i<myEntitiesAtLast.length; i++){  
                    //cast to whatever you asked for...  
                    ### myEntity = (###) myEntitiesAtLast[i];  
                }  
            }  
        }   
        catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
        
    private static void setOptions(Options options){  
        HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();  
          
        List authSchemes = new ArrayList();  
        authSchemes.add(HttpTransportProperties.Authenticator.NTLM);   
        auth.setAuthSchemes(authSchemes);   
         
        auth.setUsername(userName);  
        auth.setPassword(password);  
        auth.setHost(host);  
        auth.setPort(port);  
        auth.setDomain(domain);  
        auth.setPreemptiveAuthentication(false); //it doesnt matter...  
        options.setProperty(HTTPConstants.AUTHENTICATE, auth);  
        options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true"); //i think this is good.. not required though  




    Take a look here http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.crm.developer&tid=61c3fde8-259b-49ea-b42e-b7fa26109f61&cat=&lang=&cr=&sloc=&p=1
    This led me to that solution.

    Hope i helped

    Monday, February 2, 2009 9:39 AM
  • Hi ,
          I am very new to CRM and webservice . i generated  wsdl to  java code using ecipse . but it didn't generate CrmServiceStub to make the connection so i tried this way
    CrmService service = new CrmService(); but CRMService is interface . so i can't create a instance of this also . i tried implement class but didn't help

    please help on this is there any other way to generate the WSDL file to java ? i am not sure i am missing any file ?


    thanks in advance

    Monday, July 13, 2009 2:54 PM
  • Hi minos.ms , I used your code it is working for me for the retrivemultipe record . with out query condition . but i am trying to retrive the data with the query condition . i am getting axis fault . do you have sample code for this ? if you have can you please provide me . thanks a lot .
    Tuesday, August 11, 2009 3:30 PM
  • Dear Friends,

    I am trying to connect MSCrm thru Java client ,so I need Jars file which contains all the necessary class.

    Please send me the Jars or location of the jars where I can down load.

    Thanks in advance.

    Regard,

    Bala

    Tuesday, September 28, 2010 12:12 PM
  • Has anyone used the similar connectivity for Dynamics CRM 2011
    Wednesday, March 16, 2011 4:22 PM
  • Hi Tommie, Did you manage to connect with CRM 2011 using java?

     

    Regards

    Boudewijn

    Monday, August 22, 2011 7:34 AM
  • Hi... Very useful for me to get connected... thanks much...
    Tuesday, November 29, 2011 1:04 PM
  • Hello Snoeren and Tommie! Have you been able to connect from Java to CRM 2011 on-premises version? I have tried today to do it, but have been struggling with the authentication phase. Always receiving generic error with authentication. Do you have any tips or resources to point out?

    Regards, Matti

    Monday, April 29, 2013 1:21 PM
  • I face kind of problem you are facing for my CRM 2011. check your EventViewer for any kerberos authenticatino problem. You can also use Fiddler to check what authentication method is require from your CRM service.

    Check the first few bytes of the header

    If it starts with Negotiate TlR then you're doing SPNEGO over NTLM

    If it starts with Negotiate YII then you're doing SPNEGO over Kerberos.


    Make sure to "Vote as Helpful" and "Mark As Answer",if you get answer of your question.

    Monday, April 29, 2013 11:02 PM
  • First I was trying just to implement SOAP integration, but it seems to be much easier to use ODATA Integration service (OrganizationData.svc) instead. I was able to fetch list of company names with following Java code (newest Apache httpclient and io-utils libraries required). I noticed that there are some limitations with ODATA integration (e.g. something can't be done) etc. 

    package tests;
    
    import java.io.IOException;
    
    import org.apache.commons.io.IOUtils;
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpResponse;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.NTCredentials;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.protocol.BasicHttpContext;
    import org.apache.http.protocol.HttpContext;
    
    public class ClientTest1 {
    
    	public static void main(String[] args) throws ClientProtocolException, IOException {
    
    		DefaultHttpClient httpclient = new DefaultHttpClient();
    
    		NTCredentials creds = new NTCredentials("test-user@dynamicscrm-test.local:", "password123!", "", "");
    		httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
    
    		HttpHost target = new HttpHost("dynamicscrm-test.local", 80, "http");
    		HttpContext localContext = new BasicHttpContext();
    
    		// Execute a cheap method first. This will trigger NTLM authentication
    
    		String url = "/CrmTestDB/XRMServices/2011/OrganizationData.svc/AccountSet";
    		url += "?$select=Name";
    		HttpGet httpget = new HttpGet(url);
    
    		httpget.addHeader("Accept", "application/json");
    		HttpResponse response = httpclient.execute(target, httpget, localContext);
    		HttpEntity entity = response.getEntity();
    		// System.out.println(" Status :: " + response.getStatusLine());
    
    		for (Header header : response.getAllHeaders()) {
    			// System.out.println(header.getName() + " : " + header.getValue());
    		}
    
    		System.out.println(IOUtils.toString(entity.getContent()));
    	}
    }


    Tuesday, April 30, 2013 8:24 AM
  • Thanks for sharing a sample of your code using ODATA.  Did you have any success populating look up fields in CRM (entity reference type) or did you only need to retrieve data from CRM?
    Wednesday, July 24, 2013 1:42 PM