Scenario
An Oracle BPEL application was virtualized in WSM. When the virtualized service was tested, an "Http status code: 404" fault was encounterred .
Error Message
<faultcode xmlns="http://schemas.oblix.com/ws/2003/08/Faults">Client.UndeliverableFault</faultcode>
<faultstring>Http status code: 404</faultstring>
Diagnosis
* Checked gateway log file (OracleAS_2\j2ee\oc4j_soa\log\gateway.log) and found:
The requested URL /MyService/MySoapHttpPort was not found on this server.
* Viewed Messenger Step for Service: SID0003005 (Policy Management -> Register Services -> Services -> Click "View Details" icon -> Click "View Protocol Parameters" link) and found the HTTP Messenger URL property is set to:
http://localhost/MyService/MySoapHttpPort
Cause
* In BPEL application, "Client" partner link's WSDL imports an existing WSDL document which contains the offending dummy soap:address. During virtualization, WSM incorrectly uses it in HTTP Messenger URL.
Solution 1
* Modify HTTP Messenger URL property and point to the correct physical service endpoint
(Policy Management -> Register Services -> Services -> Click "Edit" icon -> Click "--> Modify Protocol Parameters" link)
* Save -> Save -> OK -> commit -> OK
Solution 2
* Remove the <service> section from the imported WSDL.
* Revirtualize the service.
* Caveat: you'll get a new SID
Filed under: bpel, errors, oc4j | |Comments off
* See this post for policy based fault handlings.
Partner Link Failover
* Partner link failover locations can be specified in bpel.xml
<partnerLinkBinding name="RatingService">
<property name="wsdlLocation">
http://localhost:8080/axis/services/RatingService1?wsdl
</property>
<property name="location">
http://localhost:1234/axis/services/RatingService1
http://localhost:8080/axis/services/RatingService2
</property>
</partnerLinkBinding>
Partner Link Retries
* Partner link retries can be specified in bpel.xml
<partnerLinkBinding name="FlakyService">
<property name="wsdlLocation">
http://localhost:8080/axis/services/FlakyService?wsdl
</property>
<property name="location">
http://localhost:2222/axis/services/FlakyService
</property>
<property name="retryMaxCount">2</property>
<property name="retryInterval">60</property>
</partnerLinkBinding>
Human Intervention
References
* OracleAS_2\bpel\samples\demos\ResilientDemo\ResilientFlow\ResilientFlow.pdf
Filed under: bpel, oc4j | |Comments off
Fault Policy Overview
* Since 10.1.3.3
* Catches all faults from an invoke activity (both run time and business faults)
* Overrides all catch activities in BPEL process.
* A fault policy defines conditions and their corresponding fault recovery actions.
* Fault policies are defined in multiple files under directory:
- bpel\domains\default\config\fault-policies
* XSD files are:
- bpel\system\xmllib\fault-policy.xsd
- bpel\system\xmllib\fault-policy-binding.xsd
* A fault policy can be associated at the following levels:
- Partner link
- Port type
- Process level via bpel.xml
- Domain level via fault-bindings.xml
* Fault policy binding order:
-> bpel.xml: partner link -> port type -> process
-> domain: partner link -> port type -> process
-> Catch blocks defined in bpel diagram.
SOA Fault Types
Business Faults
* Programmer defined.
* Defined in WSDL.
Runtime Faults
* Predefined, e.g.
- remoteFault
- bindingFault
* Infrastructure faults, e.g.
- Service down
- Network outage
* Data format errors
Design a Fault Policy
Create a Fault Policy File
* Create policy file (e.g. my-policies.xml) in bpel\domains\domain_name\config\fault-policies directory
Define conditions
* Conditions are based on faultName. e.g.
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
* Multiple conditions are allowed for a single faultName
- if so, conditions are evaluated sequentially
<condition>
<test>$fault.code/code="WSDLReadingError"</test>
<action ref="ora-terminate"/>
</condition>
<condition>
<action ref="ora-java"/>
</condition>
* Each condition has
- one test section which is an XPath expression against fault variable
<test>$fault.code/code="WSDLReadingError"</test>
- one action section which references to the action defined in the same file
<action ref="ora-terminate"/>
- No test condition catches all
<condition>
<action ref="ora-rethrow"/>
</condition>
- No faultName catches all faults
<faultName > . . . </faultName>
Define actions
* See examples below.
Fault Policy Examples
* Conditions
<Conditions>
<!-- when bpelx:remoteFault, retry -->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
<!-- when bpelx:bindingFault, rethrow fault -->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:bindingFault">
<condition>
<action ref="ora-rethrow-fault"/>
</condition>
</faultName>
</Conditions>
* Actions
<!-- retry Action -->
<Action id="ora-retry">
<retry>
<retryCount>8</retryCount>
<retryInterval>2</retryInterval>
<retryFailureAction ref="ora-terminate"/>
<exponentialBackoff/>
</retry>
</Action>
<!-- replayScope Action -->
<Action id="ora-replay-scope">
<replayScope/>
</Action>
<!-- rethrowFault Action -->
<Action id="ora-rethrow-fault">
<rethrowFault/>
</Action>
<!-- humanIntervention Action -->
<Action id="ora-human-intervention">
<humanIntervention/>
</Action>
<!-- abort Action -->
<Action id="ora-terminate">
<abort/>
</Action>
<!-- Custom Java Action -->
<Action id="ora-java">
<javaAction className="mypackage.myClass"
defaultAction="ora-terminate"
propertySet="propSet1">
<returnValue value="R_TRM"
ref="ora-terminate"/>
<returnValue value="R_THRW"
ref="ora-rethrow-fault"/>
</javaAction>
</Action>
- Java class must implement IFaultRecoveryJavaClass interface
public interface IFaultRecoveryJavaClass {
public void handleRetrySuccess(IFaultRecoveryContext ctx );
public String handleBPELFault(IFaultRecoveryContext ctx );
}
Associate a Fault Policy
* Process level
- Configured in bpel.xml file.
- Only one fault policy can be bound to a process, port type, or partner link.
- Multiple port types or partner links can be bound to a single fault policy.
<faultPolicyBindings>
<!-- Fault on any plink/port type not specified -->
<!-- below uses policy BillingFaults -->
<process faultPolicy="BillingFaults"/>
<partnerLink xmlns:credit="http://services.otn.com" faultPolicy="CRM_
ServiceFaults">
<!-- Fault on these 2 plink will use policy CRM_ServiceFaults -->
<name>UnitedLoanService</name>
<name>StarLoanService</name>
<!----Fault on these 2 port types uses policy CRM_ServiceFaults -->
<portType>credit:CreditRatingService</portType>
<portType xmlns:united="http://services.uninted.com/loan">
united:UnitedLoanService</portType>
</partnerLink>
<partnerLink faultPolicy="myOtherFaults">
<!-- Fault on this plink uses policy myOtherFaults -->
<name>AnotherPartnerLink</name>
</partnerLink>
</faultPolicyBindings>
* Domain level
- Configured in OracleAS_2\bpel\domains\default\config\fault-bindings.xml file.
<!-- all processes in this domain use DefaultPolicy -->
<process faultPolicy="DefaultPolicy"/>
<partnerLink faultPolicy="DefaultPolicy">
<!-- all invoke faults at partner link creditRatingService use DefaultPolicy -->
<name>creditRatingService</name>
</partnerLink>
<partnerLink faultPolicy="DefaultPolicy">
<!-- all invoke faults at specific port type use DefaultPolicy -->
<portType
xmlns:db="http://xmlns.oracle.com/pcbpel/adapter/db/insert/">db:insert_plt</portType>
</partnerLink>
Human Intervention in Oracle BPEL Control
* Login BPEL console
* Click Activities tab
* Seach activities based on states
- All States: Displays all activities, regardless of their state.
- Open: Displays only open activities.
- Completed: Displays only completed activities.
- Cancelled: Displays only cancelled activities.
- Stale: Displays only stale activities.
- Pending: Displays only pending activities.
* Click the faulted activity
* Optionally change the variable values
* Select action to take
- Retry: Retries the activity with an option to provide a retry success action.
- Abort: Terminates the process instance of the faulted activity.
- Rethrow: Rethrows the exception and allows the BPEL fault handlers (catch branches) to handle the fault.
- Replay: Replays the scope in which the fault occurred.
- Continue: Skips the activity. The framework assumes the activity completed with no fault.
* Click the Recover button.
References
* Fault Management Framework
* http://www.oracle.com/technology/tech/soa/cab/OracleSOACabWebinar03-25-08SOAExceptions.pdf
* Oracle BPEL 10.1.3.3 Fault Policy Management
Filed under: bpel, oc4j | |Comments off
Overview
* Setup Oracle AQ in Oracle database.
* Setup data source in data-sources.xml file.
* Setup resource provider in orion-application.xml.
* Setup logical JNDI names for JMS connection factories and destinations in web.xml file.
- Use <resource-ref> for connection factories.
- Use <resource-env-ref> for destinations.
* Map logical JNDI names to actual JNDI names in orion-web.xml file.
* Package into EAR file and deploy to OC4J.
Setup Oracle AQ
* See this post for details.
Setup data source
* Add to EAR data-sources.xml
<managed-data-source
login-timeout='-1'
connection-pool-name='MyAQUserDSPool'
jndi-name='jdbc/xa/MyAQUserDS'
name='MyAQUserDS'
tx-level='global'
manage-local-transactions='false'/>
<connection-pool name='MyAQUserDSPool'>
<connection-factory
factory-class='oracle.jdbc.pool.OracleDataSource'
user='MyAQUser'
password='MyAQUserPass'
url='jdbc:oracle:thin:@localhost:1521:orcl'>
<proxy-interface sql-object='Connection'
interface='oracle.jdbc.internal.OracleConnection'/>
<proxy-interface sql-object='Statement'
interface='oracle.jdbc.OracleStatement'/>
<proxy-interface sql-object='CallableStatement'
interface='oracle.jdbc.OracleCallableStatement'/>
<proxy-interface sql-object='PreparedStatement'
interface='oracle.jdbc.OraclePreparedStatement'/>
<proxy-interface sql-object='ResultSet'
interface='oracle.jdbc.OracleResultSet'/>
</connection-factory>
</connection-pool>
Setup Resource Provider
* Add to EAR orion-application.xml
<data-sources path="./data-sources.xml"/>
<resource-provider
class="oracle.jms.OjmsContext"
name="MyAQJMSResourceProvider">
<property name="datasource"
value="jdbc/xa/MyAQUserDS"/>
</resource-provider>
Setup Logical JNDI Names
* Add to WAR web.xml. Make sure to use resource-ref for connection factories and resource-env-ref for destinations.
<resource-ref>
<res-ref-name>jms/TopicConnectionFactory</res-ref-name>
<res-type>javax.jms.TopicConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-env-ref>
<resource-env-ref-name>jms/sensorConfigTopic</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
</resource-env-ref>
Map Logical JNDI Names
* Add to orion-web.xml. Make sure to use resource-ref-mapping for connection factories and resource-env-ref-mapping for destinations.
<resource-ref-mapping
name="jms/TopicConnectionFactory"
location="java:comp/resource/MyAQJMSResourceProvider/TopicConnectionFactories/MyTCF"/>
<resource-env-ref-mapping
name="jms/sensorConfigTopic"
location="java:comp/resource/MyAQJMSResourceProvider/Topics/MyAQUser.TEST_TOPIC"/>
Package into EAR File and Deploy to OC4J Container
Sample Code
* Sample code to receive message from an AQ topic.
import javax.jms.JMSException;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
public class JMSUtil {
static Logger log = Logger.getLogger(JMSUtil.class.getName());
private static final String TOPIC_CONN_FACTORY =
"java:comp/env/jms/TopicConnectionFactory";
private static final String TEST_TOPIC =
"java:comp/env/jms/TestTopic";
public static void main(String[] args) {
JMSUtil util = new JMSUtil();
TextMessage tm;
try {
tm = util.receiveTest("testId");
} catch (JMSException e) {
log.error(e);
} catch (NamingException e) {
log.error(e);
}
}
public TextMessage receiveTest(String subscriberID)
throws NamingException, JMSException {
log.debug("============================");
log.debug("Start receiveTest...");
log.debug("============================");
Context ctx = null;
TopicConnectionFactory tcf = null;
TopicConnection conn = null;
Topic topic = null;
TextMessage msg = null;
TopicSession session = null;
TopicSubscriber sub = null;
try {
ctx = new InitialContext();
log.debug("got InitialContext.");
tcf =
(TopicConnectionFactory)ctx.lookup(TOPIC_CONN_FACTORY);
log.debug("got TopicConnectionFactory.");
conn = tcf.createTopicConnection();
log.debug("got conn.");
topic = (Topic)ctx.lookup(TEST_TOPIC);
log.debug("got topic.");
session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
conn.start();
log.debug("strated conn.");
sub = session.createDurableSubscriber(topic, subscriberID);
msg = (TextMessage)sub.receive(5000);
if (msg != null){
log.debug(msg.getText());
} else {
log.debug("No message");
}
} finally {
if (sub != null)
sub.close();
if (session != null)
session.close();
if (conn != null)
conn.close();
}
log.debug("done.");
return msg;
}
}
Filed under: oc4j | |Comments off