Search code examples
androidtridiontridion-2011

Unable to connect to Tridion Core Service from an Android client


I am developing an Android app for connecting to Tridion 2011 SP1 Core Service. So far I have created Android WS Stubs from the core service wsdl using wsclient.

Imported those stubs, which allow access to all the core service methods.

I can now authenticate to Tridion via the Android application but as soon as I try to perform even the most basic of web service calls, such as getApiVersion(), I get the error:

ReflectionHelper*java.lang.NoSuchFieldException: GetApiVersionResult.

I was wondering has anyone else managed to create a java android app that communicates with the Core Service?

Interestingly enough, if I run the code as a java application, using wsimport stubs everything works a treat.

Any help appreciated. For reference here is a code snippet:

To connect to Tridion:

class TridionConnect extends AsyncTask<String, Integer, String> { 
  // Called to initiate the background activity

  @Override
  protected String doInBackground(String... statuses) {  
    try {
      Authenticator.setDefault(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
          return new PasswordAuthentication("username", "password".toCharArray());
        }
      });

      url = new URL("http://tridion-server/webservices/CoreService2011.svc?wsdl");

      System.out.println(String.format("Get Service"));
      service = new CoreService2011();
      System.out.println(String.format("Get Client"));

      client = service.getBasicHttp();

      return "Authenticated To Tridion";
    } catch (Exception e) {
      Log.e("Authentication failure", e.toString());
      e.printStackTrace();
      return "Failed to authenticate";
    }
  }

  // Called when there's a status to be updated
  @Override
  protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    // Not used in this case
  }

  // Called once the background activity has completed
  @Override
  protected void onPostExecute(String result) { // 
    Toast.makeText(FullscreenActivity.this, result, Toast.LENGTH_LONG).show();  
    area.setText("Authenticated to Tridion OK");
  }
}

To get the ApiVersion

client.getApiVersion();
UserData currentUser = client.getCurrentUser();
System.out.println(String.format("'%s' %s", currentUser.getTitle(), currentUser.getId()));

Solution

  • Frank,

    It is not possible for a couple of reasons.

    If you use wsimport to create the coreservice proxy it will use the javax library, which exists in the JRE. However Dalvik implements only a subset of the javax library which means this approach is impossible in the Android environment.

    I then looked at Ksoap2 tools for creating the proxy. This seemed to work OK, in as much as it did create a proxy, however it did not match the coreservice so I was unable to authenticate. I didn't get any further with this approach beyond examining the JRE proxy v Ksoap2 proxy. They were quite different.

    At this point I took a step back, had a cup of tea and re-engineered the approach.

    I created a c# REST service to sit between the android app and the core service.

    This approach seemed a bit complex, but it offers lots of advantages. Lots of the spade work can be done in the REST service, which will be much quicker than similar code on a tablet or phone.

    Secondly the REST service sits on the same server as the CMS/CoreService so the comms is quicker and you can make the REST requests from the android app much lighter.

    I have got the application to the point where you can authenticate to Tridion, select a publication, and components that is then rendered in a dynamic layout ready for update/save/publish.

    The one big downside of this approach is that the REST service 'should' be stateless so superficially you have to authenticate to the coreservice for every request. Of course I don't do that, but you have to come up with some alternative approach Oauth, shared secret etc.

    In initial tests this approach has seemed to be fairly slick on an android device.