Tuesday, August 18, 2015

Third Party Queue Connection using Foreign JMS Server in OSB/SOA

Hi,

There are cases where we need to establish third party JMS connection. To achieve that in ESB, we can use JMS Bridges, which creates a reliable connection oriented link to any weblogic JMS queue or to other Third Party Queue. One other way to establish the same is using Foreign JMS Server.

There are other ways listed below
Q. What tools are available for integrating with remote JMS providers?
A. The following table summarizes the tools available for integrating with remote JMS providers:
Method
Automatic Enlistment
JMS Resource Pooling
Direct use of the remote provider's JMS client
Yes for a WebLogic server provider. Other providers must perform enlistment programmatically.
No. Can be done programmatically.
Messaging Bridge
Yes
N/A
Foreign JMS Server Definition
No. To get automatic enlistment, use in conjunction with a JMS resource reference or MDB.
No. To get resource pooling, use in conjunction with a JMS resource reference or MDB.
JMS Resource Reference
Yes
Yes
Message Driven EJBs
Yes
Yes


Both of the messaging bridge and the foreign JMS server allow you to receive/send messages via a WLS server to a JMS destination that is running on a remote WLS server/cluster/domain or a 3rd party messaging product.


Conceptual Diagram


So when to use what ?

Q. When should I use a messaging bridge?
A. Typically, messaging bridges are used to provide store-and-forward high availability design requirements. A messaging bridge is configured to consume from a sender's local destination and forward it to the sender's actual target remote destination. This provides high availability because the sender is still able to send messages to its local destination even when the target remote destination is unreachable. When a remote destination is not reachable, the local destination automatically begins to store messages until the bridge is able to forward them to the target destination when the target becomes available again.

Q. When should I avoid using a messaging bridge?
A. Other methods are preferred in the following situations:
  • Receiving from a remote destination—use a message driven EJB or implement a client consumer directly.
  • Sending messages to a local destination—send directly to the local destination.
  • Environment with low tolerance for message latency. Messaging Bridges increase latency and may lower throughput. Messaging bridges increase latency for messages as they introduce an extra destination in the message path and may lower throughput because they forward messages using a single thread.


Q. When is it best to use a Foreign JMS Server Definition?
A. For this release, a Foreign JMS Server definition conveniently moves JMS JNDI parameters into one central place. You can share one definition between EJBs, servlets, and messaging bridges. You can change a definition without recompiling or changing deployment descriptors. They are especially useful for:
  • Any message driven EJB (MDB) where it is desirable to administer standard JMS communication properties via configuration rather than hard code them into the application's EJB deployment descriptors. This applies even if the MDB's source destination isn't remote.
  • Any MDB that has a destination remote to the cluster. This simplifies deployment descriptor configuration and enhances administrative control.
  • Any EJB or servlet that sends or receives from a remote destination.
  • Enabling resource references to refer to remote JMS providers. 

Here it is how you can configure it.

https://docs.oracle.com/cd/E57014_01/wls/WLACH/taskhelp/jms_modules/foreign_servers/ConfigureForeignServers.html


If you are connecting it to a third party queue, you need to have their JMS libraries in weblogic lib. For MQ it comes by default.

Now to use the JMS Server resource reference in OSB or in SOA, you can use it normally as you do for internal weblogic Queue push and pop.

In OSB, you can skip giving the host:port and jms:///ConnectionFactoryJNDI/QueueJNDI will work.

In SOA, you can configure JMS Adapter with  Connection factory location details and refer to the Queue while designing your process and it will work as it does for local queue.

Thanks









Saturday, August 15, 2015

Call Restful Certificate secured service through BPEL - Java Embedding - upload a file to a Reset Portal.

Hi,

In this post, let us see how can we use just Java through Java embedding to call a secured Restful service through SOA Suite - BPEL. Calling the restful service through Bpel whose input and output parameters are tricky has always been a confusion to developers. Though, through OSB it is easy achievable in 11g stack of Product.

So lets see, how can we achieve it through BPEL- Java Embedding.

So BPEL works on variables and we need to get the data from the variables and pass it to the java calling service, take the response into some BPEL variables as output. Thats it.

So here I would take an example of uploading File data to the certificate secured Restful portal.

For that , I need the file name, file path, the file data, the username and password of the service to be called and most importantly the Rest API URI ie the service to be called.

String fileName = ((XMLElement) getVariableData("inputVariable","payload","/client:process/client:fileName")).getFirstChild().getNodeValue();                            
       String filePath = ((XMLElement) getVariableData("inputVariable","payload","/client:process/client:filePath")).getFirstChild().getNodeValue();                                                       
       String userName = getVariableData("userName").toString();                   
       String password = getVariableData("password").toString();                   
       String fileString = filePath+"/"+fileName;  

/* audit trail is use to print the information in the Bpel Instance Audit Trail */                         

       addAuditTrailEntry("File path is " + filePath);                               
       addAuditTrailEntry("File Name is" + fileName);                               
       addAuditTrailEntry("File String is" + fileString);               
     
        String url =  ((XMLElement) getVariableData("inputVariable","payload","/client:process/client:url")).getFirstChild().getNodeValue();    
        
         DataUpload upload = new DataUpload();                  
                           
        ServerReply reply = upload.processFileUpload(url,fileString,userName,password);                  
                                       
        addAuditTrailEntry("---:SERVER REPLIED:---");                  
        addAuditTrailEntry("Staus: "+reply.getStatus());                   
        addAuditTrailEntry("Response content --");                   
    
  
        String output = reply.getReplyContent();
        addAuditTrailEntry("Sever output: "+output);                  
        setVariableData("Result",new Integer(reply.getStatus()));             
        setVariableData("outputVariable","payload","/client:processResponse/client:respMsg",output);                
                         
}                
                
 catch(Exception ex)                                
{                                 
            StringWriter sw = new StringWriter();                     
            PrintWriter pw = new PrintWriter(sw);                     
            ex.printStackTrace(pw);                     
            String errMsg= sw.toString();                     
            String error = ex.toString();                     
            addAuditTrailEntry("Error is :" +errMsg);                        
            setVariableData("outputVariable","payload","/client:processResponse/client:respMsg",error);                    
}
       

So, in the above, Java embedded code, the getVariableData() function helps in getting the data from variables and it has a particular syntax to get the data from a variable. Similar is the case for the setVariableData() function. As you can see in the piece of code that a ServerReply class has been used to take the response from calling HTTP rest Url while a DataUpload class is used to call the Restful URI.

Basically, HttpURLConnection class has been used here to call the Rest URI setting RequestProperty, DoInput, DoOutput, and RequestMethod to the calling object.And we get a reply by httpConnection.getOutputStream(); 
Now a lot can be done on the output object as per the requirement. Code is given below. Hope it will be useful.

Now lets see  the code for calling the Rest service ie the DataUpload Class.

import java.net.HttpURLConnection;
import java.net.Authenticator;
import java.net.URL;
import java.net.PasswordAuthentication;
import java.net.URLConnection;

import java.io.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import java.util.Properties;

 private static final String LINE_FEED = "\r\n";
    private static final String CHARSET = "UTF-8";
    private static final HashMap HTTP_STATUS_MESSAGES = new HashMap();    
    private static String boundary = "===" + System.currentTimeMillis() + "===";
    private PrintWriter servletOut = null;

    static {
        HTTP_STATUS_MESSAGES.put(100 , "Continue");
        HTTP_STATUS_MESSAGES.put(101 , "Switching Protocols");
        HTTP_STATUS_MESSAGES.put(200 , "OK");
        HTTP_STATUS_MESSAGES.put(201 , "Created");
        HTTP_STATUS_MESSAGES.put(202 , "Accepted");
        HTTP_STATUS_MESSAGES.put(203 , "Non-Authoritative Information");
        HTTP_STATUS_MESSAGES.put(204 , "No Content");
        HTTP_STATUS_MESSAGES.put(205 , "Reset Content");
        HTTP_STATUS_MESSAGES.put(206 , "Partial Content");
        HTTP_STATUS_MESSAGES.put(300 , "Multiple Choices");
        HTTP_STATUS_MESSAGES.put(301 , "Moved Permanently");
        HTTP_STATUS_MESSAGES.put(302 , "Found");
        HTTP_STATUS_MESSAGES.put(303 , "See Other");
        HTTP_STATUS_MESSAGES.put(304 , "Not Modified");
        HTTP_STATUS_MESSAGES.put(305 , "Use Proxy");
        HTTP_STATUS_MESSAGES.put(307 , "Temporary Redirect");
        HTTP_STATUS_MESSAGES.put(400 , "Bad Request");
        HTTP_STATUS_MESSAGES.put(401 , "Unauthorized");
        HTTP_STATUS_MESSAGES.put(402 , "Payment Required");
        HTTP_STATUS_MESSAGES.put(403 , "Forbidden");
        HTTP_STATUS_MESSAGES.put(404 , "Not Found");
        HTTP_STATUS_MESSAGES.put(405 , "Method Not Allowed");
        HTTP_STATUS_MESSAGES.put(406 , "Not Acceptable");
        HTTP_STATUS_MESSAGES.put(407 , "Proxy Authentication Required");
        HTTP_STATUS_MESSAGES.put(408 , "Request Timeout");
        HTTP_STATUS_MESSAGES.put(409 , "Conflict");
        HTTP_STATUS_MESSAGES.put(410 , "Gone");
        HTTP_STATUS_MESSAGES.put(411 , "Length Required");
        HTTP_STATUS_MESSAGES.put(412 , "Precondition Failed");
        HTTP_STATUS_MESSAGES.put(413 , "Request Entity Too Large");
        HTTP_STATUS_MESSAGES.put(414 , "Request-URI Too Long");
        HTTP_STATUS_MESSAGES.put(415 , "Unsupported Media Type");
        HTTP_STATUS_MESSAGES.put(416 , "Requested Range Not Satisfiable");
        HTTP_STATUS_MESSAGES.put(417 , "Expectation Failed");
        HTTP_STATUS_MESSAGES.put(500 , "Internal Server Error");
        HTTP_STATUS_MESSAGES.put(501 , "Not Implemented");
        HTTP_STATUS_MESSAGES.put(502 , "Bad Gateway");
        HTTP_STATUS_MESSAGES.put(503 , "Service Unavailable");
        HTTP_STATUS_MESSAGES.put(504 , "Gateway Timeout");
        HTTP_STATUS_MESSAGES.put(505 , "HTTP Version Not Supported");
    }

    public DataUpload() {
        super();
    }

 public DataUpload(PrintWriter servletOut) {
        this.servletOut = servletOut;

    }

/* Here is the function :  */

  public ServerReply processFileUpload(String url, String uploadFile,
                                         String User,
                                         String Pwd) throws Exception {

/* for the Rest URL, we open a connection to it using the mentioned class */

        HttpURLConnection httpConnection =
                                (HttpURLConnection) new URL(url).openConnection();

        String userPassword = User + ":" + Pwd;
      /* decoded is the password into BASE - 64 format */
        String userPasswordencoding =
            new sun.misc.BASE64Encoder().encode(userPassword.getBytes());

/* Through File class instantiation, the file data is uploaded into the targetFile object.
        File targetFile = new File(uploadFile);

        OutputStream outputStream;
        PrintWriter writer;
        BufferedWriter bufWriter;
        httpConnection.setRequestMethod("POST");
        httpConnection.setDoInput(true);
        httpConnection.setDoOutput(true);
        httpConnection.setUseCaches(false);
        httpConnection.setDefaultUseCaches(false);
        httpConnection.setRequestProperty("Content-Type",
                                          "multipart/form-data; boundary=" +
                                          boundary);
        httpConnection.setRequestProperty("Authorization",
                                          "Basic " + userPasswordencoding);

        outputStream = httpConnection.getOutputStream();
     
        writer =
                new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream,
                                                                          CHARSET)),
                                true);

        addHeaderField(writer, "User-Agent", "CodeJava");

        addFilePart(writer, outputStream, targetFile.getName(), targetFile);

        ServerReply reply = finish(writer, httpConnection);
        return reply;

    }

So let us see the other function s

 private void addFilePart(PrintWriter writer, OutputStream outputStream,
                            String fieldName,
                            File uploadFile) throws IOException {
        String fileName = uploadFile.getName();
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + fieldName +
                      "\"; filename=\"" + fileName + "\"").append(LINE_FEED);
        writer.append("Content-Type: " +
                      URLConnection.guessContentTypeFromName(fileName)).append(LINE_FEED);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush();
        inputStream.close();

        writer.append(LINE_FEED);
        writer.flush();
    }

    private void addHeaderField(PrintWriter writer, String name, String value) {
        writer.append(name + ": " + value).append(LINE_FEED);
        writer.flush();
    }

    private void addFormField(PrintWriter writer, String name, String value) {
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + name +
                      "\"").append(LINE_FEED);
        writer.append("Content-Type: text/plain; charset=" +
                      CHARSET).append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.append(value).append(LINE_FEED);
        writer.flush();

    }


   private ServerReply finish(PrintWriter writer,
                              HttpURLConnection httpConn) throws IOException {
        ServerReply reply = new ServerReply();

        List<String> response = new ArrayList<String>();

        writer.append(LINE_FEED).flush();
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();

        // checks server's status code first
        int status = httpConn.getResponseCode();
        reply.setStatus(status);
        //System.out.println(status);
        StringBuffer resp = new StringBuffer();
        
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedReader reader =
                new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
            String line = null;
            
            while ((line = reader.readLine()) != null) {
                resp.append(line);
                response.add(line);
            }
            reply.setReplyContent(resp.toString());
            reader.close();
            httpConn.disconnect();
        } else {
            reply.setReplyContent(getErrorMessage(status));
            throw new IOException("Server returned non-OK status: " + status + " : "+getErrorMessage(status));
        }
        reply.setContent(response);
        return reply;

    }

    private String getErrorMessage(int status){
        String errMsg= (String)HTTP_STATUS_MESSAGES.get(status);
        return errMsg;


Lets see the java class for Server Reply


import java.util.List;

public class ServerReply {
    public ServerReply() {
        super();
    }
    private int status;
    private List content;
    private String replyContent;

    public void setContent(List content) {
        this.content = content;
    }

    public List getContent() {
        return content;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public int getStatus() {
        return status;
    }

    public void setReplyContent(String replyContent) {
        this.replyContent = replyContent;
    }

    public String getReplyContent() {
        return replyContent;
    }
}



Tuesday, July 28, 2015

File Adapter Error Handling through Fault Policy Framework for rejected files.

Hi,

In this post, let us see how to handle rejected files.

File Adapters/ FTP Adapters which are used in scenarios where files are polled in SOA Suite, there are cases where corrupt or bad files can come or be present.

By default, File Adapter uses a default location to put rejected files as per the control directory which is configured in the Adapter configuration in weblogic. The instance is faulted in EM console corresponding to the rejected file case. The moment happens before an instance is created through BPEL/Mediator and after the JCA based File Adapter polls the file.

Here is a diagram which explains something about Fault Policy Framework
image : www.ateam-oracle.com

 
The fault policy framework works for File Adapter error scenarios if in place.

Here is a sample:

Below is an extract from Fault Binding xml file. A fault binding file is structured for composite, component, reference and service faults. Here, file adapter read is a service so I have added "RejectedMessages" as the fault policy to refer to. There are two composites which uses File/FTP adapter to read the files.

-ReadOrderFile
-ReadPaymentFile
 

<?xml version="1.0" encoding="UTF-8"?>
<faultPolicyBindings version="2.0.0"
                     xmlns="http://schemas.oracle.com/bpel/faultpolicy"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <composite faultPolicy="ErrorFaultPolicy"/>
    <component faultPolicy="ErrorFaultPolicy"/>
    <reference faultPolicy="ErrorFaultPolicy"/>
    <service faultPolicy="RejectedMessages">
        <name>ReadOrderFile</name>
        <name>ReadPaymentFile</name>
    </service>
</faultPolicyBindings>


Forany service related error, we can configure the Fault Policy framework to handle it.

Let us see the Fault policy file.

<faultPolicy version="2.0.0" id="RejectedMessages">
    <Conditions>
      <faultName xmlns:rjm="http://schemas.oracle.com/sca/rejectedmessages"
                 name="rjm:ReadOrderFile">
        <condition>
          <action ref="ReadOrderFile_001"/>
        </condition>
      </faultName>
      <faultName xmlns:rjm="http://schemas.oracle.com/sca/rejectedmessages"
                 name="rjm:ReadPaymentFile">
        <condition>
          <action ref="ReadOrderFile_002"/>
        </condition>
      </faultName>
...
...
...
 <Actions>
      <Action id="ReadOrderFile_001">
        <fileAction>
          <location>/../../../error</location>
          <fileName>Order_Error_%ID%_%TIMESTAMP%.dat</fileName>
        </fileAction>
      </Action>
      <Action id="ReadOrderFile_002">
        <fileAction>
          <location>/../../../error</location>
          <fileName>Payment_Error_%ID%_%TIMESTAMP%.dat</fileName>
        </fileAction>
      </Action>
...
...

So you can see here, that rejected files will be thrown to the given sample location with a generated ID and TIMESTAMP. The location and fileName tags defines those details about the File Action.

The actions are choice. We can either call a java service, a bpel composite , retry , rethrow etc for the way we want to handle the fault.

The best practice is to push the rejected files into a particular location shared to the application response for generating file data. Further, any manual/automated activity can be executed to decide actions taken on those corrupted files.

Thanks.


Friday, July 24, 2015

Dynamic Endpoint Url Invocation in BPEL

Hi,

I would like to share how to dynamically call a Web Service through BPEL using Endpoint Reference.

Firstly lets understand what use the Dynamic Endpoint Invocation could be. In scenarios where you have a good number of Services whose consumption parameters are same, ie input-output, to avoid code multiplication, we use DEI. Else a developer would end up creating as many partner links as the number of isomorphic services exists.

image : msdn.microsoft.com




First of all, you need to have the URL generated at runtime either through DVM / any source service request/ Database/ MDS etc.

In BPEL, assign the URL to a variable say ServiceToInvokeVar


ex:
 1
<assign name="Set_ServiceToInvokeVar">
      <copy>
        <from variable="inputVariable" part="payload"
              query="/ns3:******/ns3:*******/ns3:AbcsEndPointUrl"/>
        <to variable="ServiceToInvokeVar"/>
      </copy>
    </assign>
2
 <assign name="Assign_Endpoint">
      <copy>
        <from>
<EndpointReference xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing">
            <Address/>

 </EndpointReference>
</from>
        <to variable="EndpointReferenceVar" query="/ns1:EndpointReference"/>
      </copy>
      <copy>
        <from variable="ServiceToInvokeVar"/>
        <to variable="EndpointReferenceVar"
            query="/ns1:EndpointReference/ns1:Address"/>
      </copy>
      <copy>
        <from variable="EndpointReferenceVar"/>
        <to partnerLink="ABCSService"/>
      </copy>

    </assign>


If the above seems complicated to you, here I can explain here,

1. Assigned your runtime populated Endpoint to a variable say X.
2. Assign the EndpointReference WS-Addressing structure to a variable say E with null address.
3. Assign X to "/ns1:EndpointReference/ns1:Address"
4. Assign  E to your partner link.

Thats it !

Sunday, March 29, 2015

Calling a HTTPs POST REST url web service which is SSL Certificate Secured Oracle Service Bus OSB

In one of my projects, I had a requirement to call a web service which was a REST service and I had to POST XML content to the web service. The web service URL demanded to query parameters though and the service only wanted a XML to be POSTed.
The service was Certificate SSL secured with HTTPs basic authentication.

So here are the steps which I did using Oracle Service Bus.

Firstly, I went to the UNIX box the ran the below command to load the certificate from the web service.
I used the openssl utility to load the certificate. Other option is any browser to do the same. The certificates nature vary from being a chain of certificates being CA signed or a single self- signed certificate. In my case it turned out to be a single self signed certificate.
Here is the command -

openssl s_client -connect host:port | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' &gt; /..../somename.cert

Once the certificate was loaded. I had to loaded it up into the keystore of weblogic. To load it, I used the keytool utility.

Loading into the Java Keystore -

keytool -import -trustcacerts -keystore /appl/oracle/dev/fmw/11g/java/jrockit-jdk1.6.0_81/jre/lib/security/cacerts -noprompt -alias somealias -file somename.cert



Loading into the Default weblogic demoTrust keystore. Note, for production, it can be the Custom Trust store.

keytool -import -trustcacerts -keystore /appl/oracle/dev/fmw/11g/product/wlserver_10.3/server/lib/DemoTrust.jks -noprompt -alias somealias -file somename.cert

and the work for the certificate part was done.

Now, since the service was HTTPs basic authentication secured too, so an OSB Service Account was used to provide a static username and password and associate it with the Business Service.

After create the Business Service, I had too only put the XML content in the Request panel and the work was done.

Importance of Synchronous BPEL composite using File Adapter

By default, the JDeveloper wizard generates asynchronous WSDLs when you use technology adapters. Typically, a user follows these steps when creating an adapter scenario in 11g:
1) Create a SOA Application with either "Composite with BPEL" or an "Empty Composite". Furthermore, if  the user chooses "Empty Composite", then he or she is required to drop the "BPEL Process" from the "Service Components" pane onto the SOA Composite Editor. Either way, the user comes to the screen below where he/she fills in the process details. Please note that the user is required to choose "Define Service Later" as the template.
bpel_create.jpg
2) Creates the inbound service and outbound references and wires them with the BPEL component:
 
bpel_composite.jpg  3) And, finally creates the BPEL process with the initiating activity to retrieve the payload and an activity to write the payload.

bpel_process.jpg

This is how most BPEL processes that use Adapters are modeled. And, if we scrutinize the generated WSDL, we can clearly see that the generated WSDL is one way and that makes the BPEL process asynchronous (see below)

inbound_wsdl.jpg
In other words, the inbound FileAdapter would poll for files in the directory and for every file that it finds there, it would translate the content into XML and publish to BPEL. But, since the BPEL process is asynchronous, the adapter would return immediately after the publish and perform the required post processing e.g. deletion/archival and so on.  The disadvantage with such asynchronous BPEL processes is that it becomes difficult to throttle the inbound adapter. In otherwords, the inbound adapter would keep sending messages to BPEL without waiting for the downstream business processes to complete. This might lead to several issues including higher memory usage, CPU usage and so on.
In order to alleviate these problems, we will manually tweak the WSDL and BPEL artifacts into synchronous processes. Once we have synchronous BPEL processes, the inbound adapter would automatically throttle itself since the adapter would be forced to wait for the downstream process to complete with a before processing the next file or message and so on.
Please see the tweaked WSDL below and please note that we have converted the one-way to a two-way WSDL and thereby making the WSDL synchronous:
wsdl_sync.jpg
Add a activity to the inbound adapter partnerlink at the end of your BPEL process e.g.
reply.jpg

Finally, your process will look like this:
final_bpel_sync.jpg

You are done.

Please remember that such an excercise is NOT required for Mediator since the Mediator routing rules are sequential by default. In other words, the Mediator uses the caller thread (inbound file adapter thread) for processing the routing rules. This is the case even if the WSDL for mediator is one-way.

Sunday, January 18, 2015

FATAL Alert: BAD_CERTIFICATE - A corrupt or unuseable certificate was received

I am trying to invoke a third part web-service (https) through the Oracle Service Bus/Weblogic Server. However whenever I try to use a business service to connect I get the following error message:

The invocation resulted in an error: FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificate was received..


WL doesn't like wild card certs.

If you submit your request to "someserver.thirdparty.com" and you get back the above, you'll get the error.

You can 


* Disable host name verification ( never a pleasant thought )
* Write your own custom hostname verification
* Ask them to get a cert specific to their host ( with a CN of "someserver.mdsol.com, for instance ).
 


* Or apply the following method as part of Oracle given solution for WLS 10.3.6. or 10.3.5 and below  

In WLS releases before WLS 11.1.1.5 (WLS 10.3.5), WebLogic Server's hostname verification code did not support wildcard certificates. Thus as per a product enhancement, we have created a separate hostname verification code, which allows wildcard certificates.

Thus in order to have this functionality on WLS 10.3.5 and below, we have Patch 10215257 for WLS 10.3.0, 10.3.4, and 10.3.5.
NOTE: This wildcard implementation is embedded in the binaries of WLS 10.3.6 and 12.1.1.0, thus there is no requirement for a patch on those versions and higher.

Once we apply the apprropriate patch we need to do the following:

Add the server start-up parameter (in the java_options):
-Dweblogic.security.SSL.hostnameVerifier=weblogic.security.utils.SSLWLSWildcardHostnameVerifier,/div>
Navigate to Admin Console -> server_name -> SSL -> Advanced. Check the checkbox Use JSSE.

This has to be done on all the servers where we are planning to use the wild card certificate. If you are using WLS 10.3.6+ or WLS 12.1.1.0+, do the following:

Enable "Use JSSE."
Navigate to Admin console -> server_name -> SSL -> Advanced ->. Check the checkbox Use JSSE.
Select the value "weblogic.security.utils.SSLWLSWildcardHostnameVerifier" from the dropdown list of "Hostname verfication" parameters.

Note:

Weblogic server by default implements certicom SSL. In release WLS 10.3.4 the JSSE is implemented and certcom deprecated. As mentioned above.

But wth previous version i.e. 10.3 which hasn't got this option available in the console, we can implement the following parameters to enable Sun SSL implementation instead of certicom:

-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol
-Dssl.SocketFactory.provider=com.sun.net.ssl.internal.SSLSocketFactoryImpl
-DUseSunHttpHandler=true
-Dweblogic.wsee.client.ssl.usejdk=true (for webservice clients)

***If the trust authority of weblogic default certificate and provider's certificate is same then you don't need to import its certificate in your trust store.

Saturday, January 10, 2015

Weblogic WLST Script to Create JMS Artifacts in Clustered Environment

As a part one event, I had developed a WLST script to deploy JMS artifacts in a clustered environment. The script can deploy as many JMS Servers, JDBC Stores, File Stores, DQueues, DTopics with JMS Modules and Sub Deployments in a clustered web-logic environment.

Below figure depicts conventionally followed JMS Deployment Architecture.
JMS Deployment Architecture





Now let us start with the script :

There are two files as a whole. One is the python script or wlst script and the other is a properties file which contains metadata for the script.

1. createGenieJMSResources.py
2. crowdGenieJMS.properties

Let me first lay down the properties file contents.


################Start of the properties file###############

username=weblogic
password=weblogic@123
providerURL=t3://localhost:7001

#Cluster name on which the module is to be targeted
jms_clusterName=GenieCluster

#jms module and its sub deployment
jms_module=GenieModule

#files stores and data source and their respective store directory path - note: name assumed is "Store_"+jms_persistent_store_type+"_"+jms_targetManageServerName
jms_persistent_store_type=File,JDBC
optional_explicit_fileStoreDirectory=
dataSourceJNDIName=localDS

#manage servers which are to be targeted by JMS Servers and file stores respectively - note: name assumed for JMSServer is jms_module+"_JMSServer_"+jms_targetManageServerName
jms_targetManageServerName=Server-Genie1,Server-Genie2

#Destination Name and their respective jndi
jms_destination_jndi_name=jms/GenieQueue1,jms/GenieQueue2,jms/GenieQueue3,jms/GenieQueue4,jms/GenieQueue5,jms/GenieTopic1,jms/GenieTopic2,jms/GenieTopic3,jms/GenieTopic4
jms_type=Queue,Queue,Queue,Queue,Topic,Topic,Topic,Topic

#Connection Factories and their respective jndi's
jms_connFacJNDIName=fac/GenieConnFac1,fac/GenieConnFac2
xa_conn_flag=true,false

#flag for logging - if true then logs in the domain path with genieWLST.log else it stdouts on the console
log_file=true
log_path=

#flag to check if existing resources needs to be deleted and recreated, or error should log/pop out.
delete_if_exist_flag=true

#################End of the properties file#################

The important thing to note in the properties file is the comma separated values of several properties like jms_destination_jndi_name, jms_targetManageServerName. The script reads the values in a array loop on values split delimited by the ','. Look at the script code to better understand.
There are also naming convention to the file or data stores.

Now let us look at the script :


#the part contains import from java python lib. FOS and FIS is required for loading the properties file.
from java.io import FileOutputStream
from java.io import FileInputStream
from java.util import Properties
from java.io import File
import sys

try:


# Load the properties file.
def loadProperties(fileName):
properties = Properties()
input = FileInputStream(fileName)
properties.load(input)
input.close()

result= {}

for entry in properties.entrySet(): result[entry.key] = entry.value

return result


properties = loadProperties("crowdGenieJMS.properties")


#This is it checks if the WLST output files is to be generated a a user defined path or default same directory path where WLST script is kept.
if(properties['log_path']==""):
logFilePath="genieWLST.log"
else:
logFilePath=properties['log_path']+"//genieWLST.log"

#Setting the output log file
if(properties['log_file'] == "true"):
f = File(logFilePath)
fos = FileOutputStream(f)
theInterpreter.setOut(fos)


# Initializing

username = properties['username']

password = properties['password']
url = properties['providerURL']

moduleName = properties['jms_module']

subDeploymentName = moduleName+"SubDeployment"
storeType = properties['jms_persistent_store_type']

destinationJNDIName = properties['jms_destination_jndi_name']
destinationType = properties['jms_type']

CFJNDIName = properties['jms_connFacJNDIName']

clusterName = properties['jms_clusterName']


targetms = properties['jms_targetManageServerName']



# Connect to Admin Server

connect(username, password, url)
adminServerName = cmo.adminServerName


# Delete old resources, if they exist.

def deleteIgnoringExceptions(mbean):
try: delete(mbean)
except: pass

def startTransaction():
edit()
startEdit()

def endTransaction():

save()
activate(block="true")


def createUDTopic(topicName, jndiTopicName):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName) 
udt1 = create(topicName, "UniformDistributedTopic")
udt1.JNDIName = jndiTopicName

cd("UniformDistributedTopics/"+topicName)
cmo.setSubDeploymentName(subDeploymentName)
cd("/")


def createUDQueue(qname, qjndiname):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName)
udq1 = create(qname, "UniformDistributedQueue")
udq1.JNDIName = qjndiname

cd("UniformDistributedQueues/"+qname)
cmo.setSubDeploymentName(subDeploymentName)
cd("/")

def createCF(cfname, cfjndiname, xaEnabled):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName)
cf = create(cfname, "ConnectionFactory")
cf.JNDIName = cfjndiname
cf.subDeploymentName = subDeploymentName

# Set XA transactions enabled
if (xaEnabled == "true"):
cf.transactionParams.setXAConnectionFactoryEnabled(1)
cd("/")

def createJMSModule():

cd('/JMSSystemResources')
jmsModule = create(moduleName, "JMSSystemResource")

cd('/JMSSystemResources/'+moduleName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+clusterName+',Type=Cluster')], ObjectName))

# Create and configure JMS Subdeployment for this JMS System Module

sd = create(subDeploymentName, "SubDeployment")

cd('SubDeployments/'+subDeploymentName)

objName = ""
for mserver in targetms.split(','):
objName = objName + "ObjectName('com.bea:Name="+moduleName+"_JMSServer_"+mserver+",Type=JMSServer'), " 

objName="set('Targets',jarray.array(["+objName[:-2]+"], ObjectName))"

# executing python command to set target implicitly
exec objName

def createJMSServer():

i=0
ds=0
for mserver in targetms.split(','):

startTransaction()

# Assumed naming conventions
jmsServerName = moduleName+"_JMSServer_"+mserver
storeName = "Store_"+storeType.split(',')[i]+"_"+mserver


# Delete existing JMS Server and its persistent store
if(properties['delete_if_exist_flag']== "true"):
cd("/JMSServers")
deleteIgnoringExceptions(jmsServerName)

cd("/"+storeType.split(',')[i]+"Stores")
deleteIgnoringExceptions(storeName)

#Create JDBC Stores or File Stores
if(storeType.split(',')[i] == "JDBC"):
cd('/')
dsName = properties['dataSourceJNDIName'].split(',')[ds]
store = cmo.createJDBCStore(storeName)

cd('/JDBCStores/'+storeName)

cmo.setDataSource(getMBean('/SystemResources/'+dsName))
set('Targets',jarray.array([ObjectName('com.bea:Name='+mserver+',Type=Server')], ObjectName))
cmo.setPrefixName("GENIE_T_LOG_"+dsName)
ds=ds+1
else:
cd('/')
fileDir = properties['optional_explicit_fileStoreDirectory']
if fileDir == "":
fileDir = cmo.rootDirectory+"\\fileStores"+storeName

store = cmo.createFileStore(storeName)
store.setDirectory(fileDir)
cd('/FileStores/'+storeName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+targetms.split(',')[i]+',Type=Server')], ObjectName))

endTransaction()
#Committed the creation of filestores

startTransaction()
cd("/JMSServers")
# Create JMS server and assign the Filestore

jmsServer = create(jmsServerName, "JMSServer")
jmsServer.setPersistentStore(store)

cd(jmsServerName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+mserver+',Type=Server')], ObjectName))

i=i+1
endTransaction()

# The creation flow starts from here


if(properties['delete_if_exist_flag']== "true"):


startTransaction()
cd("/JMSSystemResources")
deleteIgnoringExceptions(moduleName)
endTransaction()

# Create JMS Servers along with JDBCStores or Filestores , delete the existing if required.
createJMSServer()


startTransaction()
# Create JMS Module and its subdeployment
createJMSModule()

# Create Queues and Topics : The names are same as the JNDI name tagged to the assumed Subbdeployment
di=0
for dtype in destinationType.split(','):
dname = destinationJNDIName.split(',')[di]
if(dtype == "Queue"):
createUDQueue(dname, dname)

if(dtype == "Topic"):
createUDTopic(dname, dname)
di=di+1

# Create Connection Factory with name same as JNDI tagged to the assumed Subdeployment
ci=0
for cf in CFJNDIName.split(','):
createCF(cf,cf, properties['xa_conn_flag'].split(',')[ci])
ci=ci+1

endTransaction()
except Exception, e:
dumpStack()
print e
cancelEdit("y")
#raise

disconnect()


stopRedirect()

exit()

Code shared in the below link :

https://drive.google.com/folderview?id=0B5jwUx0GPlTOZlZnNUtTNHFQYVE&usp=sharing