Monday 2 January 2017

SSL Configuration of OHS in front of WLS

 

Guys , in recent past I worked with SSL configuration of OHS 11.1.1.9 in front of WLS 10.3.6 with JDK 1.7.Sharing the steps as ready made solution for the flow Client -- HTTPS --> Oracle HTTP Server ( mod_wl_ohs ) -- HTTPS --> WebLogic Managed Server(s). For this POC , I’ve only WLS admin server & OHS standalone installation on Windows.

1. Creation of Keystore for WLS.

Created my own identity & trust store as below ,

keytool -genkey -alias selfsignedcert -keyalg RSA -sigalg SHA256withRSA -keypass welcome1 -keystore identity.jks -storepass welcome1 -validity 365

keytool -export -alias selfsignedcert -sigalg SHA256withRSA -file root.cer -keystore identity.jks
 
keytool -import -alias selfsignedcert -sigalg SHA256withRSA -trustcacerts -file root.cer -keystore trust.jks

As a result you’ll get identity.jks & trust.jks keystore created.

2. Configuration of Keystore for WLS

Configure custom identtity & custom trust for WLS , I’m not going through details for this step

Set host name verification none & client cert not requested.

Set WLS Console–> Admin server –> General –>Advanced –> .WebLogic Plug-In Enabled checked.

Set WLS Console –> Domain –> Configuration –> Web Applications –>WebLogic Plugin Enabled checked.

Set WLS Console–> Admin server –>SSL—> Advanced –> Use JSSE SSL checked.

3. That’s all from WLS side , bounce the server & access the SSL port to verify whether WLS console is opening or not.

4. Creation of Wallet for OHS.

Here I’m going to create blank wallet using orapki utility with auto login option & add the WLS certificate from identity.jks.

orapki wallet create -wallet D:\shrik\WT\Oracle_WT1\instances\instance1\OHS\ohs1\wallet -auto_login_only

orapki wallet jks_to_pkcs12 -wallet D:\shrik\WT\Oracle_WT1\instances\instance1\OHS\ohs1\wallet -keystore D:\shrik\IAM\user_projects\domains\test_domain\identity.jks -jkspwd welcome1

orapki wallet display -wallet D:\shrik\WT\Oracle_WT1\instances\instance1\OHS\ohs1\wallet

Change the patch accordingly to reflect your environment.

5. Configuration of ssl.conf for OHS

Under the SSL Virtual Host section change below

#Path to the wallet
   SSLWallet D:/shrik/WT/Oracle_WT1/instances/instance1/config/OHS/ohs1/keystores/wallet

6.Configuration of mod_wl_ohs.conf

I’m pasting mine here , paths are customized for windows,

# NOTE : This is a template to configure mod_weblogic.

LoadModule weblogic_module   D:/shrik/WT/Oracle_WT1/ohs/modules/mod_wl_ohs.so

# This empty block is needed to save mod_wl related configuration from EM to this file when changes are made at the Base Virtual Host Level
<IfModule weblogic_module>
#      WebLogicHost <WEBLOGIC_HOST>
#      WebLogicPort <WEBLOGIC_PORT>
#      Debug ON
#      WLLogFile /tmp/weblogic.log
#      MatchExpression *.jsp
 WebLogicSSLVersion TLSv1.2
</IfModule>

# <Location /weblogic>
#      SetHandler weblogic-handler
#      PathTrim /weblogic
#      ErrorPage  http:/WEBLOGIC_HOME:WEBLOGIC_PORT/
#  </Location>

<Location /console>
    SetHandler weblogic-handler
    WebLogicHost shroycho-in.in.oracle.com
    WebLogicPort 7112
    Debug ALL
    WLLogFile D:/shrik/WT/Oracle_WT1/instances/instance1/OHS/ohs1/wllog.txt
    DebugConfigInfo ON
    WLProxySSL ON
    SecureProxy ON
    Idempotent ON
    WlSSLWallet D:/shrik/WT/Oracle_WT1/instances/instance1/config/OHS/ohs1/keystores/wallet
</Location>

Highligted the lines to be added to access WLS console over SSL port via OHS.

7. Thast’s all for OHS , start the instance and try to access first OHS SSL port . Then append /console and see whether it’s redirecting to WLS SSL enabled console or not.

For any issue you can check the wllog.txt file.

Sunday 4 October 2015

Configuring OAM WebGate On OHS 12c

 

In last blog I discussed on installation of IDM 11.1.2.3.0 http://shrikworld.blogspot.in/2015/10/install-idm-111230-on-windows.html. Today I’ll go through the steps of configuring WebGate on OHS 12c .

Before get started find the certification matrix and glance through , https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CBwQFjAAahUKEwiso8ys0qjIAhWHj44KHU7rC10&url=http%3A%2F%2Fwww.oracle.com%2Ftechnetwork%2Fmiddleware%2Fid-mgmt%2Fdocumentation%2Fidentity-access-111230certmatrix-2539086.xlsx&usg=AFQjCNFZeqnxjd92TXI3GCZJ3ib8Zh40Hg&sig2=02zhQRh1Zt7oJIAR1R1mVw&bvm=bv.104317490,d.c2E.

You need to download only Oracle HTTP Server 12.1.3 from http://www.oracle.com/technetwork/middleware/webtier/downloads/index-jsp-156711.html location, NO separate WebGate installation is required as it get install along with web server.

Create a new Webtier middleware home.While installing Oracle HTTP server you need to choose one of the below 2 options,

1. Colocated HTTP Server (Managed through WebLogic server) : here Weblogic server with EMconsole extension will be installed, you can manage OHS instances from EM.

2. Standalone HTTP Server (Managed independently of WebLogic server) : Here only OHS instance and node manager will be installed.

Second options is preferred as it has less memory footprint.Once installation is done go to ORACLE_HOME\oracle_common\common\bin and start config.cmd to configure domain.select Oracle HTTP Server (Standalone) - 12.1.2.0 [ohs] and on configure node manager screen give credentials. Rest are default and complete the installation of OHS.

In my case ORACLE_HOME is C:\shrik\Apps\IDM\WebTier , to start the OHS go to C:\shrik\Apps\IDM\WebTier\user_projects\domains\wt_domain\bin and run startNodeManager.cmd.Then in separate command prompt run startComponent.cmd like startComponent ohs1 , it will prompt for nodemanager passsword like below,

image

Once done type http://localhost:7777/ and you should see OHS landing page.

As I mentioned earlier WebGate comes with OHS12c module and to configure the same follow http://docs.oracle.com/middleware/1212/webtier/WTINS/webgate.htm#WTINS1003. But I’m highlighting the commands for convenience.

To deploy WegGate,

deployWebGateInstance -w C:\shrik\Apps\IDM\WebTier\user_projects\domains\wt_domain\config\fmwconfig\components\OHS\ohs1 -oh C:\shrik\Apps\IDM\WebTier

Set the environment like set PATH=%PATH%;C:\shrik\Apps\IDM\WebTier\webgate\ohs\lib;C:\shrik\Apps\IDM\WebTier\bin

Run the EditHttpConf command by EditHttpConf -w C:\shrik\Apps\IDM\WebTier\user_projects\domains\wt_domain\config\fmwconfig\components\OHS\ohs1

Then the next step is WebGate registration ,to do that go to C:\shrik\Apps\IDM\middleware\iam_home\oam\server\rreg directory of IDM home.We’ll going to do in-band registration, under input folder you’ll get OAM11GRequest.xml template file .

Open the same and edit accordingly, like in my case

image

Then from RREG directory run \bin\oamreg.bat inband input\OAM11GRequest.xml .

image

Now go to the output folder RREG_OAM11G directory and copy cwallet.sso & ObAccessClient.xml files to C:\shrik\Apps\IDM\WebTier\user_projects\domains\wt_domain\config\fmwconfig\components\OHS\ohs1\webgate\config directory of webtier home.

Restart the ohs component and try to access http://localhost:7777/  , you will be redirected to OAM SSO login page.

You can verify the agent details from OAM console as well.

 

 

 

Saturday 3 October 2015

Install IDM 11.1.2.3.0 on Windows

 

Hello friends , today I will discuss on installing Identity Management Suite on windows 8.1 or 10 laptop , this is only for development and own RnD purpose or if you want to  show some quick demo to client , might be useful. 8GB memory is must to get started else I wouldn’t recommend you to go ahead. So guys , here are high level steps..

1. Get Installers

You can get the latest IDM suite 11.1.2.3.0 from http://www.oracle.com/technetwork/middleware/id-mgmt/downloads/oid-11gr2-2104316.html. Download Oracle Identity and Access Management 11g (11.1.2.3.0) & Oracle Fusion Middleware Repository Creation Utility 11g (11.1.1.9.0). For database download latest one 12c R1 from http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html. Download JDK 7 (64 bit) from http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html. Download generic Weblogic 10.3.6 from http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html.

2. Configuring Database

Install DB12R1 , don’t select container option and make sure AL32UTF8 character set selected, Once done we need to tune couple of parameters to run the same on low memory footprint.

Enable Oracle Database XA

Connect with sys and run @$ORACLE_HOME/javavm/install/initxa.sql & $ORACLE_HOME/rdbms/admin/xaview.sql.  This will prevent “XATRANS Views are not installed on this Database. This is required by the OIM Schema” error while running the RCU.

Tune memory

Run below commands , obviously values are of your choice though change in sga size and pga_aggregate_target is NOT mandatory.

alter system set sga_size=900M scope=spfile;
alter system set pga_aggregate_target=180M scope=spfile;
alter system set shared_pool_size=150M;
alter system set OPEN_CURSORS=900;

Alternatively you can run CREATE PFILE='C:\shrik\Apps\DB\product\12.1.0\dbhome_1\NETWORK\ADMIN\pfile.ora' FROM SPFILE;  Give your location and then edit the pfile and run create SPFILE from PFILE='C:\shrik\Apps\DB\product\12.1.0\dbhome_1\NETWORK\ADMIN\pfile.ora';

Below are the requirements basically,

show parameters PROCESSES (should be more 300)
show parameters NLS_LENGTH_SEMANTICS  (should be BYTE)
show parameters SHARED_POOL_SIZE (should be more 147456KB)
show parameters SGA_MAX_SIZE (should be more 147456KB)
show parameters DB_BLOCK_SIZE (is greater than or equal to 8KB)
show parameters OPEN_CURSORS (should be more 800)

3. Install Java

install JDK , you can skip JRE installation.’'

4.Install Weblogic

While installing weblogic create a new middleware home. Select installation type custom and de-select coherence and evaluation database.

5.Install IAM

Select the same middleware home you created earlier and complete the installation.

6.Create a new Domain

Create a OAM or IDM domain by selecting config.cmd from  <Middleware_Home>\oracle_common\common\bin directory. After completion of the same go to setDomainEnv.cmd fle of your domain.

At first line you should see set COMMON_COMPONENTS_HOME=C:\shrik\Apps\IDM\middleware\oracle_common , note down the path.

Search for set JAVA_OPTIONS=%JAVA_OPTIONS% and change/add to                                                               set JAVA_OPTIONS=%JAVA_OPTIONS% -DDISABLE_CONFIG_ENTITY=true like below,

image

7.Create DB Security store for the Domain

This step is important , go to C:/shrik/Apps/IDM/middleware/iam_home/common/tools/configureSecurityStore.py change the directory accordingly, and edit the file configureSecurityStore.py.                                         Locate the line rcu_common_path = os.path.abspath(os.path.join(os.environ["COMMON_COMPONENTS_HOME"],"jlib","rcucommon.jar")). Replace the same with                                                                                                                               rcu_common_path = os.path.abspath(os.path.join("C:/shrik/Apps/IDM/middleware/oracle_common","jlib","rcucommon.jar"))

Here we are replacing COMMON_COMPONENTS_HOME mentioned in setDomainEnv.cmd file with value, this step require for Windows 8.1 or 10, else you will get below error while running configureSecurityStore.py.

Failed to get environment, environ will be empty: (0, 'Failed to execute command ([\'sh\', \'-c\', \'env\']): java.io.IOException: Cannot run program "sh": CreateProcess error=2, The system cannot find the file specified')
Problem invoking WLST - Traceback (innermost last):
  File "C:\shrik\Apps\IDM\middleware\iam_home\common\tools\configureSecurityStore.py", line 42, in ?
  File "C:\shrik\Apps\IDM\MIDDLE~1\wls_home\common\wlst\modules\jython-modules.jar\Lib/javaos$py.class", line 256, in __getitem__
  File "C:\shrik\Apps\IDM\MIDDLE~1\wls_home\common\wlst\modules\jython-modules.jar\Lib/UserDict$py.class", line 14, in __getitem__
  File "C:\shrik\Apps\IDM\MIDDLE~1\wls_home\common\wlst\modules\jython-modules.jar\Lib/javaos$py.class", line 256, in __getitem__
  File "C:\shrik\Apps\IDM\MIDDLE~1\wls_home\common\wlst\modules\jython-modules.jar\Lib/UserDict$py.class", line 14, in __getitem__
KeyError: COMMON_COMPONENTS_HOME

Then go to C:\shrik\Apps\IDM\middleware\oracle_common\common\bin directory and run                                                 wlst C:/shrik/Apps/IDM/middleware/iam_home/common/tools/configureSecurityStore.py -v -d C:/shrik/Apps/IDM/middleware/user_projects/domains/oam_domain -c IAM -m create -p welcome1

Change the directory accordingly and the output of that should be successful, you can validate the same by                     wlst C:/shrik/Apps/IDM/middleware/iam_home/common/tools/configureSecurityStore.py -v -d C:/shrik/Apps/IDM/middleware/user_projects/domains/oam_domain -m validate   

If you still get the above error , compile and run below java file in your windows system ,

public class OpertingSystemInfo
{
    public static void main(String[] args)
    {
        // The key for getting operating system name
        String name = "os.name";       
        // The key for getting operating system version
        String version = "os.version";       
        // The key for getting operating system architecture
        String architecture = "os.arch";
       
        System.out.println("Name: " + System.getProperty(name));
        System.out.println("Version: " + System.getProperty(version));
        System.out.println("Architecture: " + System.getProperty(architecture));
    }
}

Note the output of os.name and go to C:\shrik\Apps\IDM\middleware\wls_home\common\wlst\modules directory.

Open the jython-modules.jar in 7 Zip and locate javashell.py file within that.

Search for and edit os.name accordingly (in my case I added Windows 8.1 manually)

_osTypeMap = (
      ( "nt", ( 'nt', 'Windows NT', 'Windows NT 4.0', 'WindowsNT',
                'Windows 2000', 'Windows 2003', 'Windows XP', 'Windows CE',
                'Windows Vista', 'Windows Server 2008', 'Windows 7', 'Windows 8.1' )),
      ( "dos", ( 'dos', 'Windows 95', 'Windows 98', 'Windows ME' )),
      ( "mac", ( 'mac', 'MacOS', 'Darwin' )),
      ( "None", ( 'None', )),
      )

Save and update the Jar and try to run configureSecurityStore.py again.

8. Start WLS

Start the weblogic server and oam_server1 & oam_policy_mgr1 managed server.

imageNow you should able to access OAM console ,

image 

Hope this help you installing IDM at local laptop.

Sunday 23 November 2014

Demystifying Oracle Socket Adapter

 

Spent some time today to understand how socket adapter works , how to test composite as it can’t be done from EM for inbound socket adapter. Lets assume the below use case, we have fixed length separated file , say Employee Details coming in source over some TCP port say 12112. SOA composite will bind the incoming file using NXSD and accept the stream data , then it will perform certain operation and return ACK to same socket port with some predefined code. Below are the detailed implementation steps,

1. At first create a new socket adapter outbound connection pool from weblogic console.

image 

image

Give the port no which should be free in your system, to check at your windows PC you can issue netstat -an | find "12112"  from command-prompt, else you can download TCPView from http://technet.microsoft.com/en-in/sysinternals/bb897437.aspx, it has good gui.

image

By default KeepAlive property is set as false, you can change the same to true for better performance.

2. Next create a emp.dat file like below ,

fn111111ln111111232007-01-01100
fn211111ln211111232007-11-01200
fn311111ln311111232007-12-01300

And a fixed length NXSD file to read the same,

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="
http://www.w3.org/2001/XMLSchema"
            xmlns:nxsd="http://xmlns.oracle.com/pcbpel/nxsd"
            xmlns:tns="http://shrikworld.blogspot.in/ReadEmpDetails"
            targetNamespace="http://shrikworld.blogspot.in/ReadEmpDetails"
            elementFormDefault="qualified" attributeFormDefault="unqualified"
            nxsd:version="NXSD" nxsd:stream="chars" nxsd:encoding="US-ASCII">
  <xsd:element name="EmpDetails">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Emp" minOccurs="1" maxOccurs="unbounded" nxsd:style="array" nxsd:cellSeparatedBy="${eol}">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="FirstName" type="xsd:string" nxsd:style="fixedLength" nxsd:length="8"/>
              <xsd:element name="LastName" type="xsd:string" nxsd:style="fixedLength" nxsd:length="8"/>
              <xsd:element name="Age" type="xsd:int" nxsd:style="fixedLength" nxsd:length="2"/>
              <xsd:element name="DOB" type="xsd:string" nxsd:style="fixedLength" nxsd:length="10"/>
              <xsd:element name="Salary" type="xsd:int" nxsd:style="fixedLength" nxsd:length="3"/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Create another XSD file for sync response to socket request,

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://shrikworld.blogspot.in/response"
            targetNamespace="http://shrikworld.blogspot.in/response"
            elementFormDefault="qualified">
  <xsd:element name="Response">
    <xsd:annotation>
      <xsd:documentation>
        A sample element
      </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Code" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

3. Now create a empty composite and drag-drop an inbound socket adapter, select Inbound Sync Req/Response from operation ,

image

Select the JNDI you created earlier at step#1.

image

Select request and response XSD that you created step#2,

image

Create request/response XSL for handshake like below and finish.

image

Now create a outbound file adapter to write the input data in the file.Drag and drop a BPEL component defining interface later.

image

Now go to the BPEL process and design like below,

image

It’s just any other BPEL process, screenshot of different activity,

image image

image 

Notice the last assign activity, here I’m setting ‘0x06’ to the response code, you can set any value.

image

4. Next step is important, here we’ll create request.xsl and reply.xsl.

There is a function socketReadWithXlation with that input data will be read from port and will be translated using the input message NXSD, so our request.xsl file look likes,

<xsl:template match="/">
    <xsl:copy-of select="socket:socketReadWithXlation()" />
  </xsl:template>

In sync response.xsl we need the response code that we set from BPEL process on step#3.We are going to use socketWrite function like below in the xslt,

<xsl:template match="//ns0:Response">
  <xsl:variable name="temp">
            <xsl:value-of select="/ns0:Response/ns0:Code"/>
        </xsl:variable>
    <xsl:variable name="var1" select="socket:socketWrite($temp, '','')"/>
    <xsl:variable name="var2" select="socket:socketEndOutput()"/>
  </xsl:template>

5. Now its time to test. First deploy the composite and you’ll notice that it can’t be tested from EM. You need a client program to push the data to the socket.

public class EmpClient {
    public static void main(String[] args) {
        try {
            Socket socket;
            final String HOST = "localhost";
            final int PORT = 12112;
            try {
                socket = new Socket(HOST, PORT);
            } catch (IOException ioe) {
                System.out.println(">>>");
                System.out.println(ioe.getMessage());
                System.out.println(">>>");
                throw ioe;
            }
            System.out.println("sending data: EmpDetails;");
            OutputStream os = socket.getOutputStream();
            byte[] b = "fn111111ln111111232007-01-01100\nfn211111ln211111232007-11-01200\nfn311111ln311111232007-12-01300".getBytes();
            for (int i = 0; i < b.length; i++) {
                os.write(b[i]);
            }
            os.flush();
            socket.shutdownOutput();
            System.out.println("receiving data");
            BufferedReader soc_in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String successCode = soc_in.readLine();
            System.out.println("Success Code: " + successCode);
            socket.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

You might noticed I’m sending the same data from Java code with \n separator.When you run this program you should get below output,

image

Now check the flow from EM console,

image

So we are done! You can extend this scenario based on your requirement.

Sunday 12 October 2014

Oracle Healthcare Transport Callout

 

Recently I’m involved in a Healthcare project where Oracle SOA Suite for Healthcare is being used , its cool one and easy to configure though have some limitation like explained below,

Say you are passing input message like below to an inbound SSHI endpoint where message type support has ADT 2.3.1.   For simplicity I’m using Oracle provided SSHI sample available at https://java.net/projects/oraclesoasuite11g/pages/HealthCare.

MSH|^~\&|Admission APP|Admission FAC|MyCompany APP|MyCompany FAC|20050804162010||ADT^A04|001|P|2.3.1|||AL|ER|US|ASCII|ENG
PID|||387044045||Griffin^Leo^A||20140425103329|F||||||||||309563956
OBR|1|6654831.001SAH|6654831.001SAH|POR.ABD1^PORTABLE ABDOMEN SINGLE VIEW|||201404220104|||||||||||CR^R20140422-0008|SAH^CR||||||2|1|1
OBX|1|RP|||
http://10.90.0.2/EMR/Event.asp?xyz=Study&forLoginName=test&forAccession=6654831.001SAH&forPatientPublicID=952523||||||F
OBX|2|TX|EventType

If you carefully notice MSH segment it has & as subcomponent separator. So the web URL at OBX|1| will be treated as sub –component by SSHI as it has & within URL http://10.90.0.2/EMR/Event.asp?xyz=Study&forLoginName=test&forAccession=6654831.001SAH&forPatientPublicID=952523.

So this URL is becoming http://10.90.0.2/EMR/EventInterface.asp?fun=ShowStudy^forLoginName=migdemo^forAccession=6654831.001SAH^forPatientPublicID=927952523 at output wire message of SSHI which is NOT desirable. Here transport callout come as handy and it will play a role before the translation of the message for inbound scenario and after the translation of message for outbound scenario. For more details on how transport callout works in Oracle Healthcare you care refer to Oracle doc at http://docs.oracle.com/cd/E23943_01/user.1111/e23486/hcfp_callouts.htm.

Note this transport callout works only in Linux box and does NOT work in windows system.

Here is one of the high level solution for this problem,

  1. Need java API to parse the HL7 message , in our case I’ve used HAPI API available at http://hl7api.sourceforge.net/.
  2. Replace the special char like & [which essentially one of the delimiter in MSH segment] with some predefined char , in our case I’ll replace & with +.
  3. Process the inbound message and do the transformation , if needed, at SOA layer and hit the outbound SSHI endpoint.
  4. Add a transport callout in outbound SSHI which will replace back + with & , just exactly reverse of step 1.

Lets go through in more details.

Fist pick up any sample healthcare code from Oracle site , I took 2nd one as seen below,

image

Now verify the output message of Out_Patient_Laboratory with the input message I pasted above.

Now write a java code for transport callout like below,for inbound class name is EscapeSpecialCharacters and code like below,

import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HapiContext;

import java.io.FileWriter;

import java.util.*;

import oracle.tip.b2b.callout.*;
import oracle.tip.b2b.callout.exception.*;

import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.Parser;
import ca.uhn.hl7v2.util.Terser;

public class EscapeSpecialCharacters implements Callout {
    public void execute(CalloutContext context, List input,
                        List output) throws CalloutDomainException,
                                            CalloutSystemException {
        try {
            CalloutMessage cmIn = (CalloutMessage)input.get(0);
            String inHL7Msg = cmIn.getBodyAsString();

            String v23message =
                inHL7Msg.replaceAll("\n", "\r").replaceFirst("&", "#");

            HapiContext hapiContext = new DefaultHapiContext();
            Parser parser = hapiContext.getGenericParser();
            Message msg = parser.parse(v23message);

            Terser t23 = new Terser(msg);
            //System.out.println(t23.get("/MSH-10"));
            //System.out.println(t23.get("/PID-8"));
            //System.out.println(t23.get("/OBX-5").replaceAll("&", "+"));
            t23.set("/OBX-5", t23.get("/OBX-5").replaceAll("&", "+"));

            FileWriter fw =
                new FileWriter("/oracle/fmwhome/user_projects/domains/dev_soasuite/servers/AdminServer/logs/callout_in.txt");
            fw.write(msg.encode().replaceFirst("#", "&"));
            fw.close();

            CalloutMessage cmOut =
                new CalloutMessage(msg.encode().replaceFirst("#", "&"));

            output.add(cmOut);

        } catch (Exception e) {
            throw new CalloutDomainException(e);
        }
    }
}

You need to have b2b.jar and HAPI library in class-path for successful compilation. You can see here I’m parsing through HL7 message and using Tarser I’m retrieving the value of first OBX-5 and replacing all & of web url with +. All the segment list where special chars are appearing you can pass on as a parameter of callout and can make the program more generic.

For outbound AHOutboundCallout class just does the opposite thing,

import java.io.FileWriter;

import java.util.*;

import oracle.tip.b2b.callout.*;
import oracle.tip.b2b.callout.exception.*;

public class AHOutboundCallout implements Callout {
    public void execute(CalloutContext context, List input, List output) throws CalloutDomainException, CalloutSystemException {
        try {
            CalloutMessage cmIn = (CalloutMessage)input.get(0);
            String inHL7Msg = cmIn.getBodyAsString();
            StringBuffer outputMessage =
                new StringBuffer(inHL7Msg.length());
            outputMessage.append(inHL7Msg);
            String v23message=outputMessage.toString().contains("+")? outputMessage.toString().replace("+", "&"):outputMessage.toString();
            FileWriter fw = new FileWriter("/oracle/fmwhome/user_projects/domains/dev_soasuite/servers/AdminServer/logs/callout_out.txt");
            fw.write(v23message);
            fw.close();

            CalloutMessage cmOut =
                new CalloutMessage(v23message);
            output.add(cmOut);

        } catch (Exception e) {
            throw new CalloutDomainException(e);
        }
    }
}

You might have noticed in both the cases I’m writing input and output message at callout_in.txt and callout_out.txt for verification.

Now create a callout in Healthcare after deploying the above class in jar profile . Keep all the HAPI API related jar in domain home/lib directory.

Now for inbound SSHI endpoint , Out_Patient_Admission, associate the class like below,

image

For outbound SSHI endpoint Out_Patient_Laboratory , associate the class like below,

image 

Now its time to test the solution, I’m using HAPI HL7 tester to push the message ,

image

Now verify the callout_in.txt and callout_out.txt and transport callout parameters.

callout_in.txt

MSH|^~\&|Admission APP|Admission FAC|MyCompany APP|MyCompany FAC|20050804162010||ADT^A04|001|P|2.3.1|||AL|ER|US|ASCII|ENG
PID|||387044045||Griffin^Leo^A||20140425103329|F||||||||||309563956
OBR|1|6654831.001SAH|6654831.001SAH|POR.ABD1^PORTABLE ABDOMEN SINGLE VIEW|||201404220104|||||||||||CR^R20140422-0008|SAH^CR||||||2|1|1
OBX|1|RP|||
http://10.90.0.2/EMR/EventInterface.asp?fun=ShowStudy+forLoginName=migdemo+forAccession=6654831.001SAH+forPatientPublicID=927952523||||||F
OBX|2|TX|EventType^EventType|1|StudyCompleted
OBX|3|CN|Technologist^Technologist|1

callout_out.txt

MSH|^~\&|Admission APP|Admission FAC|MyCompany APP|MyCompany FAC|20050804162010||ADT^A04|001|P|2.3.1|||AL|ER|US|ASCII|ENG
PID|||387044045||Griffin^Leo^A||20140425103329|F||||||||||309563956
OBR|1|6654831.001SAH|6654831.001SAH|POR.ABD1^PORTABLE ABDOMEN SINGLE VIEW|||201404220104|||||||||||CR^R20140422-0008|SAH^CR||||||2|1|1
OBX|1|RP|||
http://10.90.0.2/EMR/EventInterface.asp?fun=ShowStudy&forLoginName=migdemo&forAccession=6654831.001SAH&forPatientPublicID=927952523||||||F
OBX|2|TX|EventType^EventType|1|StudyCompleted
OBX|3|CN|Technologist^Technologist|1

So it’s working as expected. Note, in wire message you might see still + for web URL , this is because transport callout happen just before delivering the message to the endpoint.

You can make the program more generic by adding parameters to the transport callout.

Wednesday 21 May 2014

Communicate Between 2 Weblogic domains using SAF

 

I seen there are lots of material available in internet on implementation of Store And Forward JMS mechanism between two weblogic domains. Here in this blog I’ll repeat the same thing in simpler steps.

Configuration

1. First you need to have 2 weblogic domain up and running , for my case those two domains running on same machine.

2.For both of the domain go to domain name –>security from weblogic admin console .

image  

Select cross domain security enabled and enter credentials and confirm credentials , for my case I’ve given welcome1.It might ask you to restart the server , please do the same.

3. Now assume you are producing one message in JMS queue of domain1 and same should be available to JMS queue of domain2. So in domain1 create a file based persistence store , give physical directory location and target the same to either admin or any managed server. For my case I targeted to SOA managed server.

image

4. Create a new JMS server say TestJMSServer and point to the persistence store that you created earlier

image

5.Create a new JMS module say TestJMSModule and create a new subdeployment say TestSubDeployment which point to TestJMSServer .So whatever the resource will be created under this module will be targeted to TestSundeployment.

image

Here is my Subdeployment tab,

image

6.So now in domain1 we’ll create a TestLocalQ where the message will be produced.So add a queue resource type under TestJMSModule and give a JNDI, I’ve given jms/b2b/TestLocalQ, but it can be any unique thing.

image

7.Then create RemoteSAFContext resource under the same module and give the URL of domain2 like below,

image

The port in the URL may vary depends on where your remote queue deployed, it might be remote admin server as well instead of any managed one.Give the remote weblogic username and password.

8.Now Create a SAFErrorHandling resource under the same module like below,

image

9.Then create SAFImportedDestinations resource and select remote saf context and saf error handling from the dropdown that you have created in earlier steps. Give some prefix for JNDI prefix , it will be useful at later stage.

image

10. Go to the Queue tab of TestSAFImportedDestinations  and create a new SAF queue.Here it will ask for JNDI of local and remote queue . At step 6 we created a local queue with JNDI jms/b2b/TestLocalQ . Similarly create a queue in domain2 with some JNDI say jms/b2b/TestRemoteQ .

image

11. So we almost set, create a Store-and-forward agent from weblogic console.

image

image

12. Bounce the server, both Admin and Managed.We’ll use BPEL JMS adapter to produce message on TestSAFQueue that we created in step 10 and that message should be available to the remote queue having JNDI jms/b2b/TestRemoteQ .

After restarting the server go to SAF agent that you created in step 10 and go to monitoring tab,Verify all the sub-tabs

image

13. Now create a SOA Composite and add a JMS adapter in external reference.

image

Definitely you’ll not find the SAF queue that you created in step 10, so give any other queue name and complete the wizard selecting any XSDs.

14. Edit the jca file of JMS adapter and change the DestinationName to SAF queue JNDI,

image

To find the correct JNDI go to admin console and select the server where you targeted your JMS module and server. In my case I pointed to SOA managed server and click on JNDI tree there,

image

From the list search for JNDI prefix you gave at step 9 and copy binding name , which need to be updated in the JCA file.

image

15.Now deploy the composite and test it

image

Go to domain2 queue and check the message there.

image

Sunday 18 May 2014

Oracle B2B Healthcare Integration With Inbound ADT File

 

In recent time I’m playing with different features available in Oracle Healthcare integration , its really cool one and have enriched GUI. Tons of sample SOA projects available to get start with on OTN , below are links :

http://www.oracle.com/technetwork/middleware/healthcare/learnmore/index.html and https://java.net/projects/oraclesoasuite11g/pages/HealthCare

These will clarify all the concepts which is nothing but same as Oracle B2B product. So couple of things I noticed ,         

  1. when you create a endpoint in healthcare UI , corresponding trading partner in same name getting created in B2B.
  2. Its applicable for creation of agreement and document upload for each trading partners, but healthcare UI put an abstraction layer on B2B , so manipulation of the same are very easy.
  3. If I compare the source code for TPs after exporting the same I can notice one extra property createdByUI="fastpath-ui for healthcare endpoint which is not there for B2B TP, there might be other identifiers will explore that later.
  4. Whenever you will create send to internal queue under internal delivery channel under administration on healthcare UI , same will be created in channel marked as internal of host TP in B2B console.
  5. Whenever you will create receive from internal queue on healthcare UI same channel will be created in Administration—>Listening Channel of B2B console marked as internal.
  6. The last one which I’ll detail in this blog, whenever you configure a endpoint with transport protocol file then corresponding listening channel will be created in B2B which is NOT marked  as internal.

So while exploring the sample project I find that all are getting started using b2bsimulator like below command,                  ant -f b2bsimulator-util.xml b2bsimulatorstart -Dargs="hl7-config.properties"      where properties file have the MILP port for server and multiple clients.But I remember in B2B we used to place a file in a directory from where the listening channel used to poll and pick and interestingly I didn’t find any such sample.So in this blog I’ll go through that use case.

First prepare the SOA composite with healthcare adapter in Jdev using any ADT doc.

image

For receive below is my adapter configuration,

image

For sending the data to lab same document definition has chosen for outbound healthcare adapter configuration.In mediator just assign the value like below,

image

I also set the resequence expression in the mediator,

image 

Now deploy the composite in SOA Server.

Log in to healthcare UI and create a new endpoint with FILE as transport protocol like below,

image

Here give the polling directory and under the composite dropdown select the one that you just created above.Verify the listening channel under B2B console after enabling the same,this is what I said in point 6 above.

image

That’s all, we are ready to go, place a file in the polling folder and from SOA em console you can see the instance,

image

Go to healthcare UI report and verify the same,

image

So like B2B we can also start the healthcare integration from file polling instead of using b2bsimulator.