X
  • ADF |
    Tuesday, March 19, 2013

ADF Mobile and SDO: making the connection

One of the great difficulties in building a mobile application is building a strong web service back-end. If you are using ADF BC as your data access layer, service-enabled application modules are a compelling option. My good friend Frank Nimphius published an article in Oracle Magazine on that very topic, titled Consume Early; Consume Often

In the perspective of an ADF Mobile application, the web service methods exposed by the SDO interfaces of ADF BC view objects are accessed through the web service data control. It is worth remembering that, at this point, SDO interfaces can be reached through the SOAP protocol only. Support for REST interactions is currently planned for ADF 12c. Fortunately, the WSDL description for the service is generated by JDeveloper.

It is possible to bind directly your AMX pages to the web service data control. Shay Shmeltzer has posted a few blog entries where he uses this technique, even for calling web services with complex parameters. Some use cases, however, can be implemented more cleanly by calling the web service data control in Java code, which implies the page is bound to a bean or to a POJO-based data control. But how does one invoke the web service data control from code?

The first step is to look at the structure for the data control. Suppose I want to call the createVisit method exposed by the VisitsWS data control. The method accepts a single input parameter of type java.lang.Object

Calling the method with any random object will not work. The data control expects an object of a very specific type, with attributes matching its own definition. It is possible to determine the name of the type expected by the data control by hovering above the parameter with the mouse pointer, as shown in the screenshot below.

VisitsWS.Types.createVisit.visit is not implemented through a Java class; it is a virtual type managed by the data control. In ADF Mobile, the web service data control, when operating over the SOAP protocol, requires parameters to be passed as instances of the oracle.adfmf.util.GenericType interface. The only way to instantiate such objects is to use the GenericTypeBeanSerializationHelper class provided by the framework.  This class will transform POJO instances to and from GenericType.

Below is a  code sample that shows how to build the GenericType and  invoke the web service through the data control.

Visit visit = new Visit();

// Set attribute values for visit here.

List namesList = new ArrayList(1);

List paramsList = new ArrayList(1);

List typesList = new ArrayList(1);

GenericType gtVisit =
GenericTypeBeanSerializationHelper.toGenericType("VisitsWS.Types.createVisit.visit", visit);


namesList.add("visit");

paramsList.add(gtVisit);

typesList.add(Object.class);


try {

    AdfmfJavaUtilities.invokeDataControlMethod("VisitsWS", null, "createVisit", namesList, paramsList,
typesList);
} catch (AdfInvocationException ex) {

    // If the web service is not available throw a nice exception

    if (AdfInvocationException.CATEGORY_WEBSERVICE.compareTo(ex.getErrorCategory()) == 0) {

        throw new RuntimeException("Error with the server. Please try later.");

    }

}

There are a few things you should take into account when creating your POJO objects.

  • The attributes must have the same name as the data control attribute they are mapped to. 
  • The attributes must preferably be of type java.lang.String. Other types may work, but you may run into problems.
  • When manipulating dates, it is essential to express them in the ISO-8601 format expected by the SOAP service layer. This can be achieved through the oracle.adfmf.misc.ISO8601DateTimeUtil class.
  • If the service you invoke is based on a view object that contains attributes retrieved through a join that are marked as a reference, your POJO must declare these attributes as transient. This way, no values will be transmitted back to the server in the case of create and update operations. Failing to do so will raise a JBO exception on the server.  

By the way, if you found this post interesting, one of the two presentations I will make at the ODTUG Kaleidoscope 2013 conference in June will show you how to build flexible and SOA-compliant back-ends using Oracle ADF. See you in New Orleans! 

Join the discussion

Comments ( 7 )
  • guest Thursday, April 18, 2013

    hi,

    great explanation.

    above is about sending a single record.

    i need to send multiple record as a parameter.

    i have a List type of parameter. how to pass that to the WebserviceDC?

    thanks,

    ad


  • Blueberry Coder Friday, April 19, 2013

    Dear « Guest »,

    You cannot use a List directly for the time being. Simply declare an array of the appropriate type.

    Thank you for reading.


  • Ajay Kumar Wednesday, July 3, 2013

    Excellent...

    Thanks alot for posting such kind of great information.


  • River Saturday, March 29, 2014

    Hi...

    Followed your tutorial but Im having problem with my request data. Web service is returning error 500 because it is receiving a null request. I logged the values of the request, the GenericType variable, before invokeDataControlMethod and it has values. But when I logged the values received by the web service it is already null. Any solutions?

    Thanks.

    -River


  • Blueberry Coder Thursday, April 3, 2014

    Hi River.

    It is difficult for me to know what is happening without having a look at your code. However, the symptoms you describe seem to point to a problem with your Data Control. Have you tested your web service by accessing its WebLogic-generated test page?


  • guest Tuesday, July 15, 2014

    Hi Frederic,

    I am Trying to pass the two parameters to webservice method

    public void rejectTaskList (List taskIds, String userName )

    {

    CustomWorklistClient workFlowClient = new CustomWorklistClient( userName ) ;

    try

    {

    workFlowClient.rejectTaskList( taskIds ) ;

    }

    catch ( Exception e )

    {

    e.printStackTrace() ;

    }

    }

    one parameter is taskids and another one is user name

    could you please help me how can i pass the multiple taskids as a parameter

    Regards,

    Shankar.


  • Blueberry Coder Tuesday, July 15, 2014

    Hi Shankar.

    You should pass the task IDs as an array, not as a List. If the IDs are of type String, then the signature for your method should be public void rejectTaskList (String[] taskIds, String userName).

    Best Regards,

    Frédéric.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha