Wednesday, January 30, 2008
Scheduling processes in soa suite 11g
In the jobtype you can first define the java class file, priority, parameters and system properties
Now we can add a job set or a job definition to the project. With the job set you can run job types or job defintions parallel or serial.
In the job definition you must select a job type.
The last picture is of course the schedular. Too bad in TP3 you can't add job sets and job definitions to the schedular.
Thursday, January 24, 2008
Oracle JMS with ESB and BPEL
First we give the schema user scott permission to create a queue.
grant aq_user_role to scott;
grant execute on DBMS_AQADM to scott;
We can create the queue table
begin
sys.dbms_aqadm.create_queue_table(
queue_table => 'JMS_IN_TABLE',
queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
sort_list => 'PRIORITY, ENQ_TIME',
compatible => '10.0.0',
primary_instance => 0,
secondary_instance => 0,
storage_clause => 'tablespace users pctfree 10 initrans 1 maxtrans 255 storage ( initial 64K minextents 1 maxextents unlimited )');
end;
/
What important is that we use 'SYS.AQ$_JMS_MESSAGE' as payload type and the dequeue order is first priority and then the enqueue time.
Now we can create the queue
begin
sys.dbms_aqadm.create_queue(
queue_name => 'JMS_IN',
queue_table => 'JMS_IN_TABLE',
queue_type => sys.dbms_aqadm.normal_queue);
end;
/
If you want to dequeue and enqueue this queue we have to enable this first
begin
dbms_aqadm.start_queue( queue_name =>'JMS_IN' ,enqueue => true ,dequeue => true );
end;
/
With this plsql code we can add a message to the queue
declare
l_message clob := '';
v_enqueue_options dbms_aq.enqueue_options_t;
v_msg_props dbms_aq.message_properties_t;
v_msg_id RAW(16);
v_message SYS.AQ$_JMS_MESSAGE := SYS.AQ$_JMS_MESSAGE.construct(DBMS_AQ.JMS_TEXT_MESSAGE);
begin
l_message := '<data-message><runid>210</runid></data-message>';
v_message.set_text(xmltype(l_message).getstringval());
dbms_aq.enqueue(queue_name => 'JMS_IN'
,enqueue_options => v_enqueue_options
,message_properties => v_msg_props
,payload => v_message
,msgid => v_msg_id);
commit;
end;
/
Now we are ready to use this in the ESB. We can add a new JMS adapter in the composite view.
Choose database as oems jms provider
Create a new database connection to scott.
If you want to enqueue a message then choose produce and if you want to dequeue choose consumer
Give the resource provider a name ( we need this name later )and select the destination.
Now we add the resource provider in the application.xml in the config folder, use the same name as above
<resource-provider class="oracle.jms.OjmsContext" name="jms">
<description>oc4j-jms loop back resource provider</description>
<property name="url" value="jdbc:oracle:thin:scott/tiger@localhost:1521:orcl"/>
</resource-provider>
The last step is to configure the jms adapter. Go to the deployment folder then to the default and JmsAdapter folder. Here we edit the oc4j-ra.xml where we add a new connection
Location is the database connection name and change the user and password properties. We have to change the value of connectionFactoryLocation property. Between /resource and /QueueConnectionFactoryLocation we have to add the resource provider name.
<connection-factory connector-name="Jms Adapter" location="eis/Jms/scott">
<config-property name="connectionFactoryLocation" value="java:comp/resource/jms/QueueConnectionFactories/myQCF" encoded-credential="false"/>
<config-property name="factoryProperties" value="" encoded-credential="false"/>
<config-property name="acknowledgeMode" value="AUTO_ACKNOWLEDGE" encoded-credential="false"/>
<config-property name="isTopic" value="false" encoded-credential="false"/>
<config-property name="isTransacted" value="true" encoded-credential="false"/>
<config-property name="username" value="scott" encoded-credential="false"/>
<config-property name="password" value="tiger" encoded-credential="false"/>
</connection-factory>
Now we can use the jms queue in the esb.
Monday, January 21, 2008
Tuscany SCA java and JDeveloper 11g
JDeveloper 11G TP3 does not supports SCA Java. It is not know if it will support it in the 11g release but with 11g you can make SDO services. This is very easy, for more info see my previous blog . Let's try to use a jdev sdo service as a component in a tuscany application. I create a new jdeveloper project and add all the tuscany libraries to this project. Then create a composite file called customer.composite and put it in the root of src folder.
<?xml version="1.0" encoding="UTF-8"?>
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="/nl/ordina/hr/model/service/common/"
xmlns:dbsdo="http://tuscany.apache.org/xmlns/sca/databinding/sdo/1.0" name="customer"
xmlns:tns="/nl/ordina/hr/model/service/common/"
xmlns:types="/nl/ordina/hr/model/service/common/types/"
xmlns:errors="http://xmlns.oracle.com/adf/svc/errors/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
>
<component name="CustomerServiceComponent">
<implementation.java class="nl.ordina.soa.sdo.CustomerServiceComponent" />
<reference name="customerService"/>
</component>
<reference name="customerService" promote="CustomerServiceComponent/customerService">
<interface.java interface="nl.ordina.hr.model.service.common.serviceinterface.CustomerService" />
<binding.ws uri="http://XPCND7010XMP.work.local:8989/EJB-sdo_hr-Model-context-root/CustomerService" />
</reference>
</composite>
Here I defined a component which I can use in my app and this component uses the web service reference to connect to the sdo webservice.
Now add the sdo customer service jars to this project. We have to create a class which implements the sdo customerservice.
package nl.ordina.soa.sdo;
import java.util.List;
import nl.ordina.hr.model.dataaccess.common.CustomersViewSDO;
import nl.ordina.hr.model.service.common.serviceinterface.CustomerService;
import oracle.jbo.common.service.types.FindControl;
import oracle.jbo.common.service.types.FindCriteria;
import oracle.jbo.common.service.types.ProcessControl;
import oracle.jbo.common.service.types.ProcessData;
import org.osoa.sca.annotations.Reference;
public class CustomerServiceComponent implements CustomerService {
private CustomerService customerService;
@Reference
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
public CustomerService getCustomerService() {
return customerService;
}
public CustomersViewSDO getCustomersView(Integer customerId){
System.out.println("Called getCustomersView");
return customerService.getCustomersView(customerId) ;
}
public CustomersViewSDO createCustomersView(CustomersViewSDO customersView) {
return customerService.createCustomersView(customersView);
}
public CustomersViewSDO updateCustomersView(CustomersViewSDO customersView) {
return customerService.updateCustomersView(customersView);
}
public void deleteCustomersView(CustomersViewSDO customersView){
customerService.deleteCustomersView(customersView);
}
public CustomersViewSDO mergeCustomersView(CustomersViewSDO customersView) {
return customerService.mergeCustomersView(customersView);
}
public ListfindCustomersView(FindCriteria findCriteria,
FindControl findControl) {
return customerService.findCustomersView(findCriteria, findControl);
}
public ListprocessCustomersView(String changeOperation,
ListcustomersView,
ProcessControl processControl) {
return customerService.processCustomersView(changeOperation,customersView, processControl);
}
public ProcessData processCSCustomersView(ProcessData processData,
ProcessControl processControl) {
return customerService.processCSCustomersView(processData, processControl);
}
}
Now we can test it. Create a test class where we load the composite file and call a method of the customerservice.
package nl.ordina.soa.sdo;
import nl.ordina.hr.model.dataaccess.common.CustomersViewSDO;
import nl.ordina.hr.model.service.common.serviceinterface.CustomerService;
import org.apache.tuscany.sca.host.embedded.SCADomain;
public class Launch {
public final static void main(String[] args) throws Exception {
SCADomain scaDomain = SCADomain.newInstance("customer.composite");
CustomerService customerService = scaDomain.getService(CustomerService.class, "CustomerServiceComponent");
Integer custId = 147;
CustomersViewSDO cust = customerService.getCustomersView(custId);
System.out.println(cust.getCustFirstName()+" "+cust.getCustLastName());
scaDomain.close();
}
}
I got an error but Simon of tuscany helped me, I forgot the add @Reference to the customerService Setter.
Thursday, January 17, 2008
anyType xml message routing in ESB
Let's use xs:anyType for the xml messages. Now I don't know in the esb the structure of the xml messages. The solution is to make a main router where we use the filters and a specific xsl to extract anytype and map this to the right xsd in the next router, This router maps the data with a xsl to the db adapter.
The example main schema looks like this.
Here are two xml messages examples.
<ns1:Message xsi:schemaLocation="http://ordina.nl/esb message.xsd" xmlns:ns1="http://ordina.nl/esb" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns1:RunID>100</ns1:RunID>
<ns1:MessageType>A</ns1:MessageType>
<ns1:Data>
<MessageA>
<Text>this message A</Text>
</MessageA>
</ns1:Data>
</ns1:Message>
<ns1:Message xsi:schemaLocation="http://ordina.nl/esb message.xsd" xmlns:ns1="http://ordina.nl/esb" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns1:RunID>200</ns1:RunID>
<ns1:MessageType>B</ns1:MessageType>
<ns1:Data>
<MessageB>
<Text>this message B</Text>
<SubMessageB>
<Text>this message B</Text>
</SubMessageB>
</MessageB>
</ns1:Data>
</ns1:Message>
Let's do this in the 10.1.3 esb. I use for this example file adapters. Make a esb project and start by dragging the file adapter to the esb file. The file adapters reads the xml's in a directory and this file adapter is based on the anytype message schema.
Now we need to make a xsl where we extract the anytype to a new xml. This is how the xsl looks.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:n="http://ordina.nl/esb" xmlns="http://ordina.nl/esb">
<xsl:template match="/n:Message">
<xsl:for-each select="n:Data">
<xsl:copy>
<xsl:attribute name="RunID"><xsl:value-of select="//n:RunID"/></xsl:attribute>
<xsl:attribute name="MessageType"><xsl:value-of select="//n:MessageType"/></xsl:attribute>
<xsl:copy-of select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Let's apply this xsl to the two mail handling messages and generate ( I use Altova xmlspy) two new schema's on the new xml's, we need these schema for the specific routers. Now we can make the outgoing message A file adapter, use the new schema message A and make a messageA Router too. Use for this router also the new schema message A. Make a routing rule between the message A router and the message A file adapter.
We can do the same for the xml message B.
Now we have to make the routing rules on the main router. First we set the filters. We test the ns1:MessageType element if it equals A or B.
Then we make a xsl where we add the namespaces of the above xsl and replace the standard xsl:template with the xsl:template of the above xsl. See picture below for the xsl. This xsl can we use by all the main router rules.
The esb diagram looks like this, you can deploy it to the esb server and put xml message A or message B in the In folder. The esb puts now the messages in the right Out folder.
Here you can download the esb example project
Tuesday, January 15, 2008
external application in webcenter 11g
Oracle creates for this an own credential store where it store your credentials and Oracle also provides a taskflow to manage these accounts. Too bad in TP3 you can configure it and run it in Webcenter but you can't login somehow. It looks very promising. But how can you use it in webcenter 11g? First we select the viewcontroller and right click -> New. Now we can select external application item under the General Category. Let's use otn forums as example.
Now we have to look at the page source of the otn login page to find the login url and the type of action. The next step is to find the name of the login and the password field. If you at the page source of the login page. We see that the action = https://login.oracle.com/sso/auth and the method is post etc.
Now we can add the hidden fields to the external application. With the otn site we have v,site2pstoretoken and locale as additional fields.
The next step is shared credentials for logged in user. If you leave this empty every user have to provide its own credentials and the last step is the public credentials for not authenticated users. With shared and public credentials you don't have to log in, you see the external direct. Now we have to create a new pdk java producer
We have to provide an url endpoint use http://localhost:6688/jpdk/providers/external and select associate producer with external applicatin and select otn.
In the application resourcez we can see now the otnForums producer with the flight portlet.
Now we can drag the flight portlet to the jsf page. Make sure you add security to the project and to the page. The last step is to add the extapp-change-password-taskflow from the webcenter resource view to the jsf page so we can change passwords for these external applications and with this taskflow you can use the personal credential store. We can run now the jsf portal page
Sunday, January 13, 2008
ADF taskflow method call with complex return types
Process is the method call with its own pagedef. In the router I check the return status attribute so it knows to return the taskflow with a succes or abort.
To call the bpel web service I use an ADF web service datacontrol. This generates a datacontrol see picture below.
Now we can drag the process method of the creditcheck datacontrol to the taskflow. We get the following wizard where we can define the values of the input variables.
It generates the following pagedef.
MethodName="process" IsViewObjectMethod="false"
DataControl="CreditCheck" InstanceName="CreditCheck"
ReturnName="CreditCheck.methodResults.process_CreditCheck_process_result">
NDValue="${data.items_trainPageDef.CustomerId.inputValue}"
NDType="java.lang.Integer"/>
NDValue="${data.items_trainPageDef.OrderId.inputValue}"
NDType="java.lang.Integer"/>
NDValue="${data.items_trainPageDef.OrderTotal.inputValue}"
NDType="java.lang.Float"/>
The return = CreditCheck.methodResults.process_CreditCheck_process_result. To evaluate the status we must add a methoditerator on the result. We do this in the pagedef.
Now we can add the status attributevalue to pagedef.We have to click "add" button to generate an accessorIterator first
Now we select the process_Result of the process method
We return to the create attribute binding dialog and now we can select the status attribute. The method call pagedef looks like this
version="11.1.1.47.96"
id="WEB_INF_order_task_flow_definition_order_task_flow_definition_process"
Package="nl.ordina.order.view.pageDefs">
RangeSize="25"
BeanClass="nl.ordina.order.view.CreditCheck.process"
id="processIterator"/>
RangeSize="25" DataControl="CreditCheck"
BeanClass="nl.ordina.order.view.CreditCheck.process_Result"
id="process_ResultIterator"/>
MethodName="process" IsViewObjectMethod="false"
DataControl="CreditCheck" InstanceName="CreditCheck"
ReturnName="CreditCheck.methodResults.process_CreditCheck_process_result">
NDValue="${data.items_trainPageDef.CustomerId.inputValue}"
NDType="java.lang.Integer"/>
NDValue="${data.items_trainPageDef.OrderId.inputValue}"
NDType="java.lang.Integer"/>
NDValue="${data.items_trainPageDef.OrderTotal.inputValue}"
NDType="java.lang.Float"/>
Now we can use the status attributevalue in the router. If status is true then the outcome is succes else the default outcome is used ( abort)
Wednesday, January 9, 2008
Tagging and searching in Webcenter 11G
What do you need to get tagging working. First you have to use taskflow ( adfc-config.xml ) In this unbounded taskflow we create the pages. We have to do this so we can click on tagged item and then it re-directs to the right page. On the jsf page we add the tagging button from the component palette ( Webcenter tagging service) . Now we have to fill in the resourceId #{facesContext.viewRoot.viewId} , this is important to link the page to the tag. In my case #{facesContext.viewRoot.viewId} = document . If I click on a tagged item then the unbounded taskflow knows which page this is and redirects to document page.
Now we add from the resource palette the tagging-launch-dialog taskflow. This is needed for the tagging popup. Add the search-toolbar taskflow to the page too.
We have to add security to the page by using the adf security wizard then open the pagedef of the jsf page so we can add view rights to the jsf page. Go to the structure window of the pagedef and start edit autorization and give the roles oc4j-administrator and oc4j-app-administrators customize, personlize and view rights.
The last step is to create the webcenter database schema and create a database connection named WebCenter in jdeveloper and we are ready to give it a testdrive.
Here you see the search toolbar and a Tags link (tagging button) Now if I click on the Tags link, the tags dialog pops up. Here we can add tags. Use the shared tag option if you want to share the tags with others
Now it's time to search for a tag. In this case I add java to the search input and start searching. A search dialog pops up and it shows the tag java and the items where it is found. In my case are that the document and search page. I can click this and it jumps to this page. Because I have a content repository connection it searches in this too.
If we click on the tag "java" then we see this more detail search page. Here we can see who has created this tag
Tuesday, January 8, 2008
Todo tasks in soa suite and webcenter 11g
We start first the soa suite server. Create a new webcenter project in jdeveloper. On the just created viewcontroller project we start the adf security wizard. Create a jsf page and drop from the resource panel the taskflow-task-service component on the jsf page.
Go to the pagedef definition of this jsf page and add by the page security the view action to the view.
The last security step is to configure the role permissions. Go the to the structure window of the pagedef and start edit autorizations. Let's give the roles oc4j-administrator and oc4j-app-administrators customize, personalize and view rights.
We have to create a new worklist service connection. We only have to fill in the soa suite url and we are done.
Now we can start the webcenter jsf page and log in as oc4jadmin. Here we can see all the oc4jadmin tasks. We can create a new task.
Let's log in as oc4jadmin in the bpm worklist application ( http://localhost:8988/integration/worklistapp/ ). Here we can see the new to do task which we created from the webcenter page.
We can create in this worklist application a new To do task. If we refresh the webcenter jsf page we don't see this task. We have to tweak this a little bit. Log in with sqlplus to the soa schema and execute the following sql statement, update wftask t set t.textattribute2 = 'oc4jadmin' where t.owneruser = 'oc4jadmin' . Now refresh the webcenter page and we see the task which we created in the bpm application.
Sunday, January 6, 2008
Using links in the document library service Webcenter 11g
We can select or search an other document and link this to the first document
Now we see the relation between the two documents.
And if you only have view right you will see this. You don't get link buttons
Friday, January 4, 2008
Create taskflows or portlets in Webcenter 11g
If your company only uses Oracle technology then you should use taskflow and you can always deploy it as a portlet to the webcenter container. The portlet bridge works fine now( PPR and Popup works now) and we can use mds to customize the taskflow. If you want to build portlets because you don't know if you want to use the oc4j container then make sure that you don't use specific oracle technology else you get errors on the other j2ee containers.
Wednesday, January 2, 2008
Document library service in webcenter 11g
In this blog I will show how easy it is to have this working on your own file system. First we make a content repository connection. I use file system as repository type and my ebooks folder as base url.
We drag the doclib-document-library taskflow from the resource palette on a jsf page. Go to Webcenter Services Catalog and open the task flow folder.
Now we need the name of the content repository connection, in my case ${'MyEbooks'} and the start folder ${'/'}.
We are finished and ready to run the jsf page. Here is an another picture of a search action on my ebooks.