(WID/WPS) Issue CWWBF0060E : com.ibm.websphere.sca.ServiceRuntimeException: Component not found

This particular exception is nothing to do with the coding or deployment, its just a build issue.
This exception arises while running any business process (from any test client) when there is problem in building the EJB project.

This is how this can be solved.

Solution 1 :
1) Make sure you have closed all opened file taking part in building the project (Better do not open any file)
2) Clean build & then deploy.

Solution 2 :
1) Go to Resource Perspective delete all .class files carefully.
2) Do clean then build. (on EJB project only!)
3) Ensure you have no EJB related files open ( as this does cause problems)
4) Go back to The Integration perspective then clean + build.  


(WID/WPS) Testing components using Ant Script

This post shows how to test component developed in WID using a script.


In scenarios where we do regression testing with predefined set of test data, its very tedious to do manual testing. Ideally we should create a test project for the module with test cases under a Test suite.


Below diagram show a snapshot of Test suite testing:


Script:
<project name="Automated OP Test Case Run" basedir="." default="run">
<property name="test" value="ScriptTest"/>
<property name="module" value="Script"/>


   <!-- Running the component test project to test the application end to end -->
   <target name="test">
      <get dest="C:/OPTest.xml" src="http://localhost:9081/${test}Web/TestServlet"/>
   </target>


In above script "Script" is the name of the module & ScriptTest is Test project.
It also exports test result in specified location which is C:/OPTest.xml in above example.


We can also run all the test cases of a test suite using this url
http://localhost:9081/ScriptTestWeb/TestServlet


TestServlet is a servlet (com.ibm.wbit.comptest.ct.servlet.TestServlet)


PI

(WID/WPS) Security QOS

Security Identity qualifier specifies the identity under which implementation will run at the runtime. A role is specified to the identity. This role dictates whether the component or implementation is authorized to invoke downstream methods. Security Identity is equivalent to the RunAs Role used for delegation in Websphere Application Server.


One of the steps to deploy secured application is to assign users and groups to the Roles that were defined when the application was constructed. This step can be achieved by following the step entitled as "Map security Roles to User and Groups". You can add new users and groups or modify the existing information during this step.


One more step that one has to configure which is entitled as "User RunAs Role". In this step you have to sepcify the user name and password of a user and assign to a role. Important is that user for which you have entered username and password should be the member of that role.

For example, if the RunAs role is assigned user "bob", and the client, "alice", is invoking a BPEL component that invokes method on other secured component, then invocation will happen under the identity of 'bob'. In this case 'bob' must be a authorized user to the invoked secured component. If the user is not authorized a security permission exception is raised.

For more info

http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/index.jsp?topic=%2Fcom.ibm.websphere.wps.doc%2Fdoc%2Ftsec_deploying.html

Scenario 1 (Setting the Security permission)


Case 1 : When user is not assigned to any role, currently user is harish

Result : 
[6/15/12 12:14:57:191 IST] 000002d0 ExceptionUtil E   CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "transactionRequiredActivitySessionNotSupported" on bean "BeanId(SecuritySampleApp#SecuritySampleEJB.jar#Module, null)". Exception data: com.ibm.websphere.sca.ServiceRuntimeException: Permission denied: harish is not in role Caller



Case 2 : When user/group , this time its user = harish is assigned to the Caller role.





Assigning harish to Caller role.



Result : Worked correctly.

Scenario 2 (Setting the Security Identity)





Note : Here privilege = ProIdentity

Case 1 : When no Run as property is set.
Result:

[6/15/12 12:26:07:273 IST] 000002cd ServiceLogger I com.ibm.ws.ffdc.IncidentStreamImpl initialize FFDC0009I: FFDC opened incident stream file C:\Program Files\IBM\WID62\pf\wps\logs\ffdc\server1_000002cd_12.06.15_12.26.07_0.txt
[6/15/12 12:26:07:273 IST] 000002cd ServiceLogger I com.ibm.ws.ffdc.IncidentStreamImpl resetIncidentStream FFDC0010I: FFDC closed incident stream file C:\Program Files\IBM\WID62\pf\wps\logs\ffdc\server1_000002cd_12.06.15_12.26.07_0.txt
[6/15/12 12:26:07:273 IST] 000002cd ExceptionUtil E   CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "transactionRequiredActivitySessionSupports" on bean "BeanId(SecuritySampleApp#SecuritySampleEJB.jar#Module, null)". Exception data: com.ibm.websphere.sca.ServiceRuntimeException: The run-as authentication data is not configured for role ProIdentity.....

Case 2 : Caller  : managers group , ProIdentity : harish







Result:
[6/15/12 12:37:41:887 IST] 000002cb ExceptionUtil E   CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "transactionRequiredActivitySessionNotSupported" on bean "BeanId(SecuritySampleApp#SecuritySampleEJB.jar#Module, null)". Exception data: com.ibm.websphere.sca.ServiceRuntimeException: Permission denied: harish is not in role Caller

Note : Here harish is not a member of managers group (which is actually mapped to the Caller role)

Case 2 : Caller  : managers group , ProIdentity : man & ProIdentity Role is assigned to man & harish users.




Note : Here man is a member of managers group.

Result : Worked properly

Attached PI

(WID/WPS) Integrated Test Client

This post is kind of must read post for all WID/WPS developers, because what we develop today, we test that sooner or later with unit or integration testing.


Highlights of the post are:
  • Component Testing.
  • Module Testing.
  • Testing modules from external application (Attaching to a module)
  • Emulation (Manual/Programmatic)
  • Creating reusable Test Cases.
  • Data pool (Reusing values)
  • Testing using Ant script 


Few very very useful links:


Getting the most out of the WebSphere Integration Developer integration test client
http://www.ibm.com/developerworks/websphere/techjournal/0712_gregory/0712_gregory.html


Taking component testing to the next level in WebSphere Integration Developer
http://www.ibm.com/developerworks/websphere/library/techarticles/0806_gregory/0806_gregory.html


Testing SOA applications with WebSphere Integration Developer and Ant scripts
http://www.ibm.com/developerworks/websphere/library/techarticles/0903_bist/0903_bist.html


A doc on test client
http://publib.boulder.ibm.com/infocenter/ieduasst/v1r1m0/topic/com.ibm.iea.wid_v7/wid/7.0/Testing/WBPMv7_WID_TestClientLab.pdf

(WID/WPS) How does Human Task Manager work ?

Prerequisite for this post is basic understanding of human tasks.


When we model a human task, we can set a verb and a parameter that can be used to build a query to the user registry.Tasks are then created and assigned for all users in the result set of that query.


Below figure shows the link between modeling time and runtime. 
The attribute role of an activity is set to Potential Owner.
The verb is set to Group Members and the parameter to Approvers.
At runtime, this is used to build a SELECT ALL query. This query returns two users, John and Jane. John and Jane are members of the group Approvers and become potential owners of this new task.

Assigning tasks to users at runtime


Interaction between HTM & user registry


The Human Task Manager runs as a container within the application server.It is accessible through SCA or by way of specific APIs.These APIs or the client SCA interface can create a new task.When a new task is created, it follows following steps:

  • HTM retrieves information from its database to build the query.
  • HTM passes the query to the Staff Plug-in Provider using the Staff Service.
  • The query is executed against the staff repository to retrieve a user or group of users.
  • The query results are returned to the HTM.
  • The new tasks that are created for the selected users are then stored in the database by the HTM.

(WID/WPS) Sending/Receiving Message using JMS Export



Following code shows how to use JMS export binding to send message to the mediation module & get response back from the same.


Flow is like:
JMS Export ->> Mediation Module ->> Web Service Import (Can be any service provider)


Code Snippet for JMS Client :
try{
String icf = "com.ibm.websphere.naming.WsnInitialContextFactory";


//the Provider URL
String url = "iiop://localhost:2809";


//The Queue Connection Factory used to connect to the bus
String sampleQCF = "jms/sampleQCF";


//The Queue used to send requests to the mediation module
String sampleSendQueue = "jms/profileServiceExportIn";


//The Queue used to receive responses from the mediation module
String sampleReceiveQueue = "jms/profileServiceExportOut";


//The XML representation of a Profile which is the Business Object required by the add operation on the ProfileService Interface.
String message = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
message += "<profile xmlns:ns2=\"http://BookOrderResources\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"ns2:Profile\">";
message += "<name>"+request.getParameter("name")+"</name>";
message += "<address>";
message += "<street>"+request.getParameter("street")+"</street>";
message += "<city>"+request.getParameter("city")+"</city>";
message += "<country>"+request.getParameter("country")+"</country>";
message += "</address>";
message += "<creditCardNum>"+request.getParameter("creditCardNum")+"</creditCardNum>";
message += "<lastUpdate>2006-02-16</lastUpdate>";
message +=  "</profile>";


java.util.Hashtable env = new java.util.Hashtable();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, icf);
env.put(javax.naming.Context.PROVIDER_URL, url);
javax.naming.Context ctx = new javax.naming.directory.InitialDirContext(env);


//Lookup the ConnectionFactory
javax.jms.ConnectionFactory factory = (javax.jms.ConnectionFactory)ctx.lookup(sampleQCF);


//Create a Connection
javax.jms.Connection connection = factory.createConnection();


//Start the Connection
connection.start();


//Create a Session
javax.jms.Session jmsSession = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);


//Lookup the send Destination
javax.jms.Destination sendQueue = (javax.jms.Destination) ctx.lookup(sampleSendQueue);


//Create a MessageProducer
javax.jms.MessageProducer producer = jmsSession.createProducer(sendQueue);


//Create the TextMessage that will hold out profile as text
javax.jms.TextMessage sendMessage = jmsSession.createTextMessage();


//Set the content of the message to be the XML defined Profile
sendMessage.setText(message);


//Set the operation to call on the ProfileService interface to be add
sendMessage.setStringProperty("TargetFunctionName", "add");


//Send the message
producer.send(sendMessage);


//Lookup the receive Destination
javax.jms.Destination receiveQueue = (javax.jms.Destination) ctx.lookup(sampleReceiveQueue);


//Create a MessageConsumer
javax.jms.MessageConsumer consumer = jmsSession.createConsumer(receiveQueue);


//Wait 15 seconds to receieve the response
javax.jms.TextMessage receiveMessage = (javax.jms.TextMessage) consumer.receive(15000);


if (receiveMessage != null) {
System.out.println(receiveMessage.getText());
}


//Close the Connection
connection.close();
}
catch (Exception e) {
e.printStackTrace();
}


Server run time configuration:

We need to create both the queues & QCF along with activation specification so that the module can register the input queue with its message listener as follows:

  • Click Resources → JMS Providers → Default messaging.
  • Under Activation Specifications, click JMS activation specification.
  • Click New to create an activation specification 
    • Set the name field to sampleAS.
    • Set the JNDI name field to jms/sampleAS.
    • Select the destination type as Queue.
    • Set the Destination JNDI name to jms/profileServiceExportIn.
    • Select the SCA.APPLICATION.esbCell.Bus bus from the Bus name menu.


Following are the screen shots for business object & interface:


Business objects used in ProfileService interface


 ProfileService interface
Attached PI


(WID/WPS) Mapping Bindings

One of the crucial functionality provided by WESB is the protocol transformation or in other words "transport binding transformation".


In the example given below I have done mapping from SOAP/HTTP Web service binding to JMS binding.


Background:
Bindings can be defined on an import or export. On an export, they describe how a client or an SCA component communicates with the mediation module. On an import, they describe how the mediation module communicates with the defined service.


Server Runtime configuration:
Creating a new Destination (Queue)
  • Run the administrative console and log in.
  • Select Service integration -> Buses.
  • Click the SCA.APPLICATION.xxxCell.Bus link. (xxx is either wid or esb)
  • Under Destination resources on the right-click Destinations.
  • We will see two predefined destinations, a topic, and a queue.
  • Click New to create a new destination on the bus.
  • The next screen shows four types of destination that can be specified. Select
  • Queue and click Next.
  • The queue attributes screen is displayed. Enter JMSImportOut as the identifier
  • then click next & complete the queue attribute creation.


Creating a QCF & Queue
  • Select Resources -> JMS Providers -> Default messaging.
  • Under Connection Factories, click JMS queue connection factory, click New.
  • Fill in the properties of the queue connection factory:
    • Set the Name as sampleBindingQCF.
    • Set the JNDI Name to jms/sampleBindingQCF.
    • From the list for Bus name, choose SCA.APPLICATION.xxxCell.Bus.
    • Click OK at the bottom of the screen.

  • Select Resources -> JMS Providers -> Default messaging.
  • On the right, under Destinations, click JMS queue and then click New.
  • Create the queue.
    • Set the Name to JMSImportOut.
    • Set the JNDI Name to jms/JMSImportOut.
    • Select SCA.APPLICATION.xxxCell.Bus from the Bus Name menu.
    • Select JMSImportOut from the Queue Name menu.
    • Click OK at the bottom of the screen.
  • Click the Save link at the top of the console and confirm the changes to the master configuration by clicking Save.


After successful completion code & testing, to the message in queue follow the below steps:
  • Select Service integration -> Buses -> SCA.APPLICATION.xxxCell.Bus -> Destinations -> JMSImportOut -> Queue points -> JMSImportOut@xxxNode.server1-SCA.APPLICATION.xxxCell.Bus.



  • We can see the current message depth is 1, to see whats there in message,click the Messages link in Additional properties (right)


  • Now click on Identifier link to see the message body.
Attached PI

(WID/WPS) FlatFile Inbound Adapter issue & fix

If you deploy your application to WebSphere Process Server 6.1 or 6.2 containing WebSphere Application Server 6.1.0.23 through 6.1.0.25, the polling function does not work for inbound adapter

Here is the fix, just one property needs to be set.
Very very useful as I wasted approx a month to get it done :(

http://www-304.ibm.com/support/docview.wss?rs=695&context=SSMKUK&dc=D600&uid=swg21394864&loc=en_US&cs=UTF-8&lang=en



(WID/WPS) Dynamic EndPoints in Mediation Flow

The concept of Dynamic End Points provide the runtime support, in fact it provides an enhancement to the WESB (and WPS) runtime to: 
  • Allow the mediation programming model to select (or to influence the selection of) service endpoints at the runtime.
  • Allow the selection at runtime of a service endpoint that has not been predefined in the mediation flow 
With the support provided by Dynamic End Points, the mediation flow designer 
can use a Callout Node in the flow in a dynamic way. For a dynamic callout, the associated reference provided on the component need not be wired to an import. At runtime, the dynamic callout retrieves an element from the SMO which provides the endpoint address to be used by the callout as the service endpoint.

Note : The highlighted property should be checked to achieve this functionality.


Callout Node property to get dynamic behaviour

The endpoint address can be passed along with the input message or can be retrieved within the flow by calling db or performing any business logic.

This endpoint address should be mapped to /headers/SMOHeader/Target/address using a map or custom mediation primitive.


Mapping of  endpoint address to '/headers/SMOHeader/Target/address'

Following are assembly diagrams for ServiceProvider & DynamicEndpointsPOC projects :





Note : There is no wiring from DynamicLookup Mediation component to any of the import as it will be determined at runtime by callout node.



How to run : We can have a client project to call the standlalone reference asking user for the endpoint address :
  • For calling the SCA export binding : sca://ServiceProvider/JavaCompExport
  • For calling the webservice export binding  : http://localhost:9081/ServiceProviderWeb/sca/IServiceExport1
  • For calling the HTTP export binding : http://localhost:9081/ServiceProviderWeb/HttpCompExport/doTest
How to call a standalone reference : http://harishonsoa.blogspot.com/2012/04/standalone-reference-client.html

Attached the PI
Note : HTTP binding works only if  Data objects are used for input & output.


Alternative way of setting the SMOHeader.Target :

String port = "9081";
String hostname = "localhost"; 
String URI = "http://"+hostname+":"+port+"/";
String serviceIdentification = 
 ((commonj.sdo.DataObject)smo.getContext().getTransient() ).getString("ID");
if(serviceIdentification.equals(" Provider1"))
   {
      URI = URI + "Export1";
   }
   else if(serviceIdentification.equals("Provider2"))
   {
      URI = URI + "Export2";
   } 
com.ibm.websphere.sibx.smobo.TargetAddressType targetAddress = 
   com.ibm.websphere.sibx.smobo.ServiceMessageObjectFactory
   .eINSTANCE.createTargetAddressType(); 
targetAddress.setAddress(URI);
smo.getHeaders().getSMOHeader().setTarget(targetAddress);
out.fire(smo);

Updated on April 4th, 2017


In cases, alternate endpoints need to be configured (Actual endpoint failed and mediation should retry to alternate endpoints), this can be done as below:


<context>
    <dynamicProperty>
      <propertySets>
        <group>CalleeMediation.ServiceProviderMediationFlow</group>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryCount</name>
          <value>3</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryDelay</name>
          <value>2</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.retryOn</name>
          <value>1</value>
        </properties>
        <properties>
          <name>ServiceProviderInfcPartner_processName_Callout.tryAlternateEndpoints</name>
          <value>true</value>
        </properties>
      </propertySets>
    </dynamicProperty>
  </context>
  <headers>
    <SMOHeader>
      <MessageUUID>387185A6-015B-4000-E001-563E8EAE73C4</MessageUUID>
      <Version>
        <Version>7</Version>
        <Release>0</Release>
        <Modification>0</Modification>
      </Version>
      <Target>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExportWrong</address>
      </Target>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExporta1</address>
      </AlternateTarget>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExpora2</address>
      </AlternateTarget>
      <AlternateTarget>
        <address>http://localhost:9080/CalleeMediationWeb/sca/ServiceProviderInfcWSExport</address>
      </AlternateTarget>
    </SMOHeader>
  </headers>


Callout Prop:






Above promoted properties can be configured on need basis.


TryAlternateEndpoints should be true to try alternate endpoints otherwise it will retry same endpoint (based on retryCount value)

Retry_On=1

#Retry on values
# Never - 0
# Any fault - 1
# Modeled fault - 2
# Unmodeled fault – 3

Code:

DynamicPropertySetType dynamicPropertySet = ServiceMessageObjectFactory.INSTANCE.createDynamicPropertySetType();
dynamicPropertySet.setGroup("CalleeMediation.ServiceProviderMediationFlow");

PropertyType property1 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property1.setName("ServiceProviderInfcPartner_processName_Callout.retryCount");
property1.setValue(Retry_Count_Value));

PropertyType property2 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property2.setName("ServiceProviderInfcPartner_processName_Callout.retryDelay");
property2.setValue(Retry_Delay_Value));

PropertyType property3 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property3.setName("ServiceProviderInfcPartner_processName_Callout.retryOn");
property3.setValue(Retry_On_Value));

PropertyType property4 = ServiceMessageObjectFactory.INSTANCE.createPropertyType();
property4.setName("ServiceProviderInfcPartner_processName_Callout.tryAlternateEndpoints");
property4.setValue(TryAlternateEndpoints_Value));


// Add the properties
dynamicPropertySet.getProperties().add(property1);
dynamicPropertySet.getProperties().add(property2);
dynamicPropertySet.getProperties().add(property3);
dynamicPropertySet.getProperties().add(property4);

DynamicPropertyContextType dynamicPropertyContext = ServiceMessageObjectFactory.INSTANCE.createDynamicPropertyContextType();
dynamicPropertyContext.getPropertySets().add(dynamicPropertySet);
smo.getContext().setDynamicProperty(dynamicPropertyContext);
 
TargetAddressType targetAddress1 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress1.setAddress(URI1);

TargetAddressType targetAddress2 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress2.setAddress(URI2);

TargetAddressType targetAddress3 =   ServiceMessageObjectFactory.eINSTANCE.createTargetAddressType();
targetAddress3.setAddress(URI3);

smo.getHeaders().getSMOHeader().getTarget().setAddress(URI4);

smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress1);
smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress2);
smo.getHeaders().getSMOHeader().getAlternateTarget().add(targetAddress3);