Thursday Feb 27, 2014

Consuming Async SOA in a WebService Proxy

Consider a scenario where an application is built using SOA Async processes and needs to be consumed in a WebService Proxy. In this blog, we will be demonstrating how to implement this use case. To achieve this, we will follow a two step process:

  1. Create an Async SOA BPEL process.
  2. Consume it in a WebService Proxy.

Pre-requisite:

 Jdeveloper with SOA extension installed.

Steps:

To begin with step 1, create a SOA Application and name it SOA_AsyncApp.

This invokes Create SOA Application wizard. In the wizard, choose composite with BPEL process in Step 3.


As we are going to build an async processes, in Create BPEL Process dialog, choose Asynchronous BPEL Process from Template drop-down. We will be using BPEL 1.1 Specification for our process. Also, make sure the process is exposed as a SOAP service.


We can see the two one-way operations listed in the process wsdl as it is an async process:

Drag and drop assign activity from Components onto the SOA Composite.


Edit the assign activity to insert a new rule from input variable payload to output variable payload. Click on the Plus symbol to add the rule.

Now, the Async service setup is complete and the project containing Async process can be deployed to a SOA server. With this, we are done with Step 1 of our use case.

To create a proxy for this service, create a custom Application SOA_AsyncProxy. Invoke Create Web Service Proxy wizard and in Step 2 of wizard, give WSDL of the service developed in Part1 of this blog.  In Step 3, check ‘Generate As Async ’ checkbox and give Callback Package name CallBackPackage.

In step 5, make sure generate async method radio button is selected and finish the wizard.

After proxy is generated, run the Callback Service from under the package CallBackPackage. This service will listen to the response from the asynchronous service. Give target URL of Callback Service in proxy class and call the process with appropriate input value.


Run the proxy. Following sequence of actions will take place after proxy is run:

1) The proxy will invoke the SOA process asynchronously and continue with other tasks.

2) SOA async service will store the request and send receipt confirmation (202) to the proxy.

3) The service processes the request and acting as a proxy for Callback Service, sends the response back to the Callback Service.

      4) Callback service, deployed on the proxy side receives the response and sends a confirmation to the async SOA service (202).

After the callback service receives the response, it has to map the response to the request. This is achieved using WS-Addressing Headers. The proxy must set two fields to establish the correlation: 1) ReplyTo address (address of the Callback Service) and 2) A unique Id to identify the request.

Async behavior can be verified by logging in to EM console and examining the flow instance of BPEL Process.


The correct payload in the callbackProxy confirms that async operation has been executed successfully.

Thursday Feb 13, 2014

ADF Desktop Integration Server Logging

About

In my last blog, I have discussed on how to enable logging on ADFdi client. Here let us see on how to enable server-side logging to obtain detailed error stack.

Adding log-handler and logger for desktop integration

In <JDEV_HOME>\jdeveloper\system<version>\DefaultDomain\config\fmwconfig\servers\DefaultServer\logging.xml file, add log-handler for desktop integration by copying below code inside <log-handlers>.

<!-- The log handler for ADFdi -->
<log_handler name="oracle-adf-desktopintegration-logging-handler" class="oracle.core.ojdl.logging.ODLHandlerFactory">
<property name="path" value="../log/adfdi/msglogging"/>
<property name="maxFileSize" value="10485760"/>
<property name="maxLogSize" value="104857600"/>
<property name="encoding" value="UTF-8"/>
</log_handler>

Note: Provide valid value for path property.

Loggers can be added for below packages

  • All ADF Desktop Integration server logic: name = oracle.adf.desktopintegration
  • ADF Desktop Integration HTTP filter: name = oracle.adf.desktopintegration.filter

oracle.adf.desktopintegration: This package generates logs for all Servlet logic(DIRemoteServlet) and Download filter logic(DIExcelDownloadFilter) of ADFdi.

In logging.xml, inside <loggers>, comment the existing logger for oracle.adf.desktop.integration.
Eg: <!--logger name='oracle.adf.desktopintegration' useParentHandlers='true'/-->

Add new logger by copying below code inside <loggers> tag.

<!-- The logger for ADFdi -->
<logger name="oracle.adf.desktopintegration" level="INFO">
<handler name="oracle-adf-desktopintegration-logging-handler"/>
</logger>

Different Levels:

INFO : Information, warning and error messages will be logged into the log file present in the specified path.
WARNING: Only warning and error messages will be logged.
ERROR: Only error messages will be logged.
FINE/FINER/FINEST: More detailed log messages can be obtained by setting these levels.

oracle.adf.desktopintegration.filter: This package generates logs only for Download filter logic(DIExcelDownloadFilter) of ADFdi.

In logging.xml, inside <loggers>, comment the existing logger for oracle.adf.desktop.integration.
Eg: <!--logger name='oracle.adf.desktopintegration' useParentHandlers='true'/-->

Add new logger by copying below code inside <loggers> tag.

<!-- The logger for ADFdi -->
<logger name="oracle.adf.desktopintegration.filter" level="FINE">
<handler name="oracle-adf-desktopintegration-logging-handler"/>
</logger>

Different Levels:

INFO: Logs only two messages- one at startup and one at termination of Excel Download Filter.
FINE/FINER/FINEST: Detailed logs can be obtained by setting these levels.

After adding loggers or changing levels for loggers, weblogic server has to be restarted for changes to get effected.
To configure loggers while the application is running in Integrated Weblogic server, see the "Using the ADF Logger" section in Developing Fusion Web Applications with Oracle Application Development Framework.

Tuesday Feb 04, 2014

HTTP Basic Auth in REST Client

When a web service is secured using basic authentication, the client can access the web service only after providing the appropriate credentials.

In this blog, I take you through the code which will enable the client to access such a service.

Pre-requisites:

Use JDeveloper 12c  version or above.

Creating the Service:

Let us start by creating a REST service and securing it with basic authentication. 

For creating the service, please refer the section "Creating the service" in blog.

Basic Authentication setup:

Once the REST service has been created, in order to secure it using basic authentication, follow the below steps:

Open the web.xml file. At the end of the file, add the lines:

<login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>myrealm</realm-name>
    </login-config>
    <security-constraint>
        <web-resource-collection> 
           <web-resource-name>MyResource</web-resource-name> 
           <url-pattern>/*</url-pattern> 
        </web-resource-collection> 
        <auth-constraint> 
           <role-name>MyRole</role-name> 
        </auth-constraint> 
    </security-constraint>
    <security-role> 
        <role-name>MyRole</role-name> 
    </security-role> 
</web-app>

Next, you need to create a weblogic.xml file. For this, go to New Gallery -> General -> Weblogic Deployment Descriptor.

weblogic xml file

On clicking Ok, another popup appears. Under Select Descriptor, select weblogic.xml and click Next. Select the deployment descriptor version in accordance with your weblogic version and then click Finish. This will generate a weblogic.xml file under WEB-INF. Open weblogic.xml file and select 'Security' from LHS. Under 'Security Role Assignments', add the Role Name 'MyRole', and add the Principals 'Administrators' as shown.

Configuring weblogic.xml file

At this point, your web service has been secured using basic authentication mechanism. Run the service and copy the generated WADL URL. This will be used to create the proxy for the service.

Accessing the service through REST Client:

First, to create the REST Client, create a new Custom Project.Let us name it ClientProj. Right click on the Project and invoke the New Gallery window. Under Business Tier -> Web services category, select REST Client and Proxy. Provide the generated WADL URL and click Next.

A prompt will appear asking for username/password.

Credential pop up

Provide the Administrator username and password that you would use to log into the WLS Console.On providing the correct credentials and clicking on Finish, the client class gets generated with some in-built code. Within the class 'Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java' auto generated for you, write the following lines:


public class Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient {
    public static void main(String[] args) {
        Client client = Localhost_EmployeeServiceEmployeeProjContextRootResources.createClient();

        Localhost_EmployeeServiceEmployeeProjContextRootResources.Employeeproj localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj =
            Localhost_EmployeeServiceEmployeeProjContextRootResources.employeeproj(client);
        
        // add your code here
        client.addFilter(new HTTPBasicAuthFilter("weblogic","weblogic1"));
        System.out.println(localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class));
    } 

Use the import as below:

import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;

We use the HTTPBasicAuthFilter provided by Jersey to pass the basic auth credentials. Refer link for more details.

Alternate method:

Alternately, within the public class Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java auto generated for you, write the following lines:

public class Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient {
    public static void main(String[] args) {
        Client client = Localhost_EmployeeServiceEmployeeProjContextRootResources.createClient();

        Localhost_EmployeeServiceEmployeeProjContextRootResources.Employeeproj localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj =
            Localhost_EmployeeServiceEmployeeProjContextRootResources.employeeproj(client);
        
        // add your code here
        Authenticator.setDefault(new MyAuthenticator());
        System.out.println(localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class));
    }
    
    static class MyAuthenticator extends Authenticator {    
        public PasswordAuthentication getPasswordAuthentication() {
                
        return (new PasswordAuthentication("weblogic", "weblogic1".toCharArray()));
            }
        } 

Use the imports:

import java.net.Authenticator;

import java.net.PasswordAuthentication;

Here, in the code block above, we basically extend the Authenticator class, and override the getPasswordAuthentication method, in which we pass the username and password. (Replace username and password above with the credentials you provided to create the client class)

In the main method, we then invoke the setDefault method of the Authenticator class and pass our Authenticator class name. This method will set the credentials whenever a proxy or HTTP server asks for authentication. The next two lines are for invoking a method of the service.

If you run the client code by supplying incorrect credentials, you will get a 401 Unauthorized error.

About

Tips and Tricks from Oracle's JDeveloper & ADF QA

Search

Archives
« February 2014 »
SunMonTueWedThuFriSat
      
1
2
3
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
28
 
       
Today