Показаны сообщения с ярлыком BPEL. Показать все сообщения
Показаны сообщения с ярлыком BPEL. Показать все сообщения
, ,

Зависающая активити Wait (hanging activity wait)

среда, 25 ноября 2009 г. 0 коммент.

Во время возросшей нагрузки, подвисла активити Wait. Поиск по интернету и чтение документации помогли найти решение.

Необходимо изменить значение параметра com.oracle.bpel.expirationAgent.threadCount с 10 до 150.

Параметр находится в файле resources-quartz.properties по следующему пути ${BPEL_HOME}/bpel/domains/{name of domain}/config.

Подробнее, какие еще параметры можно настроить можно почитать в BPEL Performance Tuning: Quartz Scheduling. Как работает активити Wait можно узнать в BPEL Performance Tuning: Quartz Scheduling.

Читать полностью

, , ,

Удаление BPEL Instance’ов и Human Task’ов.

четверг, 8 октября 2009 г. 0 коммент.

Иногда надо почистить BPEL инстансы и очень хочется, чтобы это происходило автоматически. Для ручного удаления можно воспользоваться BPEL консолью, но там есть большой недостаток – не возможно удалить все дерево связанных процессов. Чтобы это можно было сделать я написал небольшой пакетик. Одна процедура удаляет Human Task’и, другая связанные BPEL инстансы и Human Task’и.


create or replace package bpel_enhancement is

procedure delete_ci( p_cikey in cube_instance.cikey%type
,p_ignore_root in boolean default false
);

procedure delete_wt(p_taskid in wftask.taskid%type
);

end bpel_enhancement;
/
create or replace package body bpel_enhancement is

procedure delete_ci( p_cikey in cube_instance.cikey%type
,p_ignore_root in boolean default false
)
is
vi pls_integer;
begin

-- Проверим сначала, что инстанс не имеет родителей
select count(1)
into vi
from cube_instance
start with cube_instance.cikey = p_cikey
connect by to_char(cube_instance.cikey) = prior to_char(cube_instance.parent_id);

if (vi = 0) then
raise_application_error(-20000, 'Не найден инстанс "' || p_cikey || '"');
elsif (vi > 1) then
if not p_ignore_root then
raise_application_error(-20000, 'Найдены родительские процессы для инстанса "' || p_cikey || '"');
end if;
end if;

-- начинаем удалять иерархически в обратном порядке
for vCur in (
select cube_instance.*
from cube_instance
start with cube_instance.cikey = p_cikey
connect by prior to_char(cube_instance.cikey) = to_char(cube_instance.parent_id)
order by level desc
) loop
-- Удаляем инстанс
dbms_output.put_line('Удаление истанса: "' || vCur.Cikey || '" -- "' || vCur.Title || '"');
collaxa.delete_ci(p_cikey => vCur.cikey);

-- Ищем связанные задачи
for vCurTask in (
select *
from wftask
where wftask.instanceid = vCur.cikey
) loop

dbms_output.put_line('Удаление задачи: "' || vCurTask.Taskid || '" -- "' || vCurTask.Tasknumber || '"');
delete_wt(vCurTask.Taskid);
end loop;
end loop;

end delete_ci;

procedure delete_wt(p_taskid in wftask.taskid%type
)
is
begin
delete from wftaskhistory where taskid = p_taskid;
delete from wfassignee where taskid = p_taskid;
delete from wfattachment where taskid = p_taskid;
delete from wfcomments where taskid = p_taskid;
delete from wfmessageattribute where taskid = p_taskid;
delete from wfnotification where taskid = p_taskid;
delete from wfnotificationmessages where taskid = p_taskid;
delete from wfroutingslip where taskid = p_taskid;
delete from wftasktimer where taskid = p_taskid;

delete from wftask where taskid = p_taskid;
end delete_wt;

end bpel_enhancement;
/

Читать полностью

, , , ,

Таймаут при вызове bpel-процесса

среда, 18 марта 2009 г. 0 коммент.

При вызове сервиса в Oracle BPEL cтолкнулся с такой ошибкой "java.lang.IllegalStateException: Cannot call setRollbackOnly() current thread is NOT associated with a transaction".

Ошибку также можно найти в логе по следующему пути:
"SOA_Oracle_Home\opmn\logs\".
Смотрим файл лога для контейнера в котором крутиться BPEL.

Поиск по документации привел к следующему решению.
A.1.1 Setting Properties for BPEL Processes to Successfully Complete and Catch Exception Errors

Следует обратить внимание не следующие особенности:
1. Параметр transaction-timeout в файле "SOA_Oracle_Home\j2ee\home\config\transaction-manager.xml".
1.1. На самом деле необходимо изменять файл, который повлияет на контейнер в котором крутиться bpel, т.е. правильный путь будет "SOA_Oracle_Home\j2ee\КОНТЕЙНЕР_ГДЕ_КРУТИТЬСЯ_BPEL\config\transaction-manager.xml"
1.2. Для исталяции одинокого Oracle BPEL Process Manager файл надо искать здесь "SOA_Oracle_Home\bpel\system\appserver\oc4j\j2ee\home\config".
2. Параметр transaction-timeout в файле "SOA_Oracle_Home\j2ee\home\application-deployments\orabpel\ejb_ob_engine\orion-ejb-jar.xml".
2.1. Также надо искать по другому пути.
"SOA_Oracle_Home\j2ee\КОНТЕЙНЕР_ГДЕ_КРУТИТЬСЯ_BPEL\application-deployments\orabpel\ejb_ob_engine\orion-ejb-jar.xml".
2.2. Обязательно поменять параметр во всем файле, он встречается несколько раз, для каждого бина.
3. Параметр syncMaxWaitTime в "SOA_Oracle_Home\bpel\domains\domain_name\config\domain.xml"
3.1. Не забываем поменять параметр для каждого домена.

Перестартовываем Application Server.

Иногда при длительном ожидании ответа от bpel-процесса, можно поймать ошибку "500 Server Error". В данном случае ругается Apache.
Что бы увеличить таймаут ожидания, находим параметр Timeout в файле "SOA_Oracle_Home\Apache\Apache\conf\httpd.conf" и увеличиваем значение. Перестартовываем Apache. Читать полностью

, , ,

Как получить userName из WS-Security soap-заголовка, способ 2

вторник, 17 февраля 2009 г. 0 коммент.

Я уже писал тут, как можно получить userName из soap-заголовка.
Теперь это можно сделать еще одним способом, зарегистрировав свой custom step в wsm.
Для этого в wsm идем по этой дорожке "Policy Management > Manage Policies > Steps", нажимаем "Add New Step" и указываем путь к конфигурационному xml-файлу своего custom step'а.

В файле указываем название шага, java-пакет, который реализует наш шаг, идентификатор, и одно свойство "Enabled" - разрешен или запрещен шаг.


<csw:StepTemplate
xmlns:csw="http://schemas.confluentsw.com/ws/2004/07/policy"
name="owsmcustomstep"
package="test_owsmcustomstep"
timestamp="Oct 15, 2007 05:00:00 PM"
version="1"
id="200902051">

<csw:Description>Custom step test</csw:Description>

<csw:Implementation>test_owsmcustomstep.CustomTestStep</csw:Implementation>

<csw:PropertyDefinitions>
<csw:PropertyDefinitionSet name="Basic Properties">
<csw:PropertyDefinition name="Enabled" type="boolean">
<csw:Description>If set to true, this step is enabled</csw:Description>
<csw:DefaultValue>
<csw:Absolute>true</csw:Absolute>
</csw:DefaultValue>
</csw:PropertyDefinition>
</csw:PropertyDefinitionSet>
</csw:PropertyDefinitions>
</csw:StepTemplate>

Ниже представлен класс, который реализует custom step.
Сначала получаем сообщение, возвращаем его в виде XML-документа. Находим имя пользователя и элемент, куда запишем это имя. После этого создаем новое сообщение на основе измененного XML-документа и возвращаем его.

package test_owsmcustomstep;

import com.cfluent.policysteps.sdk.AbstractStep;
import com.cfluent.policysteps.sdk.IMessageContext;
import com.cfluent.policysteps.sdk.IResult;
import com.cfluent.policysteps.sdk.Result;
import com.cfluent.policysteps.sdk.Fault;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.apache.axis.message.SOAPEnvelope;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class CustomTestStep extends AbstractStep {
private PrintWriter out = null;

public CustomTestStep() {
}

public void init() throws IllegalStateException {
try {
out = new PrintWriter(new BufferedWriter(new FileWriter("log/CustomTestStep.log", true)));
}
catch (Exception e) {
String errMsg = "Error in creating log file for custom step:" + e.getMessage();
System.err.println(errMsg);
e.printStackTrace();
throw new IllegalStateException(errMsg);
}
}

/**
* Used for cleaning up any resources created in the init() method
* It is called during server shutdown or when the policy is updated.
*/
public void destroy() {
out.close();
}

private void log(String str) {
try {
Date d = new Date();
DateFormat df = new SimpleDateFormat("HH:mm:ss yyyy/MM/dd");

out.println(df.format(d) + ":1158: " +str);
out.flush();
} catch (Exception ex) {
System.err.println("Exception encountered when writing to file");
ex.printStackTrace();
}
}

private void logSOAPMessage(SOAPMessage soapMsg) {
String msg = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
soapMsg.writeTo(baos);
msg = baos.toString();
log("CustomTestStep: Request SOAP message is " + msg);
} catch (Exception ex) {
System.err.println("Exception encountered while converting SOAP message to a String");
ex.printStackTrace();
}
}

public IResult execute(IMessageContext messageContext) throws Fault {
log("CustomTestStep: Entering");

IResult resultStatus = new Result();
resultStatus.setStatus(IResult.FAILED);

try {
//Getting the SOAPMessage object from the context
SOAPMessage soapMessage = messageContext.getRequestMessage();
// loging request
logSOAPMessage(soapMessage);

SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = (SOAPEnvelope)soapPart.getEnvelope();

String namespaceURI_soap = "http://schemas.xmlsoap.org/soap/envelope/";
String namespaceURI_wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

// get XML-Document
Document document = soapEnvelope.getAsDocument();
Element rootElement = document.getDocumentElement();
// element, where put username
Element elementInput = null;
String username = null;

// search username
if(rootElement != null) {
Element header = getToken(rootElement, "Header", namespaceURI_soap);
if(header != null) {
Element securityHeader = getToken(header, "Security", namespaceURI_wsse);
if(securityHeader != null) {
Element usernameTokenElement = getToken(securityHeader, "UsernameToken", namespaceURI_wsse);
if(usernameTokenElement != null) {
Element usernameElement = getToken(usernameTokenElement, "Username", namespaceURI_wsse);
if(usernameElement != null) {
username = usernameElement.getTextContent();
}
}
}
}
}

// search element
if(rootElement != null) {
String namespaceURI_ns1 = "http://xmlns.oracle.com/test_soap";
Element body = getToken(rootElement, "Body", namespaceURI_soap);
if(body != null) {
elementInput = getToken(body, "input", namespaceURI_ns1);
}
}

if (username != null && elementInput != null) {
elementInput.setTextContent(username);
}

//Convert the Document object to a String Object
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
StringWriter strWriter = new StringWriter();
StreamResult streamResult = new StreamResult(strWriter);
transformer.transform(domSource, streamResult);
String xmlString = strWriter.toString();

//Convert this string object to a SOAPMessage object
MessageFactory messageFactory = MessageFactory.newInstance();
MimeHeaders mimeheaders = new MimeHeaders();
mimeheaders.addHeader("Content-Type", "text/xml");

// IMPORTANT : The following is very important especially if your
// SOAP message would contain UTF-8 data like European characters etc.
ByteArrayInputStream soapByteArrayInputStream = new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
SOAPMessage newSoapMessage = messageFactory.createMessage(mimeheaders, soapByteArrayInputStream);

//Set the SOAP Request back into the context
messageContext.setRequestMessage(newSoapMessage);

// logging new request
logSOAPMessage(messageContext.getRequestMessage());
log("CustomTestStep: Exiting");
resultStatus.setStatus(IResult.SUCCEEDED);

} catch (Exception ex) {
String errMsg = ex.getMessage();
log("CustomTestStep: Error:" + errMsg);
generateFault(errMsg);
}

return resultStatus;
}

private Element getToken(Element parentElement, String tokenName, String tokenNameSpaceURI)
{
Element token = null;
NodeList nodeList = parentElement.getElementsByTagNameNS(tokenNameSpaceURI, tokenName);
if (nodeList != null) {
token = (Element)nodeList.item(0);
}
return token;
}

}

Примеры для создания custom step в WSM можно найти на metalink:How To read a SOAP Message into an XML Document & back into a SOAP Message?

Читать полностью

, , ,

Соответсвие WSDL рекомендациям WS-I версии 1.1

понедельник, 26 января 2009 г. 0 коммент.

Обычная ситуация: делаешь сервисы, они хорошо работают.
Но тут приходит время использование сервисов внешними системами и оказывается, что сделанные сервисы не соответсвуют рекомендациям WS-I и хоть это и рекомендации, но внешние системы все эти рекомендации соблюдают, а твои сервисы нет. :(

Рассмотрим один случай. Есть WSDL.


<?xml version="1.0" encoding="UTF-8"?>
<definitions
name="test_wsdl"
targetNamespace="http://xmlns.oracle.com/test_wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:ns1="http://xmlns.oracle.com/test_scheme"
xmlns:client="http://xmlns.oracle.com/test_wsdl">
<!--> start cut
...
end cut </!-->
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://xmlns.oracle.com/test_scheme"
schemaLocation="test_scheme.xsd"/>
</xsd:schema>
<!--> start cut
...
end cut </!-->
</types>
<message name="test_wsdl_getdata1RequestMessage">
<part name="payload" element="ns1:Request"/>
</message>
<message name="test_wsdl_getdata1ResponseMessage">
<part name="payload" element="ns1:Response"/>
</message>
<message name="test_wsdl_getdata2RequestMessage">
<part name="payload" element="ns1:Request"/>
</message>
<message name="test_wsdl_getdata2ResponseMessage">
<part name="payload" element="ns1:Response"/>
</message>
<!--> start cut
...
end cut </!-->
<portType name="test_wsdl">
<operation name="getdata1">
<input message="tns:test_wsdl_getdata1RequestMessage"/>
<output message="tns:test_wsdl_getdata2ResponseMessage"/>
</operation>
<operation name="getdata2">
<input message="tns:test_wsdl_getdata2RequestMessage"/>
<output message="tns:test_wsdl_getdata2ResponseMessage"/>
</operation>
<!--> start cut
...
end cut </!-->
</portType>
<binding name="test_wsdlBinding" type="tns:test_wsdl">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getdata1">
<soap:operation style="document" soapAction="subscribe"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="getdata2">
<soap:operation style="document" soapAction="getdata"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<!--> start cut
...
end cut </!-->
</binding>
<service name="test_wsdl">
<port name="test_wsdlPort" binding="tns:test_wsdlBinding">
<soap:address
location="http://myhost:80/orabpel/domain_test/test_wsdl/1.0"/>
</port>
</service>
<plnk:partnerLinkType name="test_wsdl">
<plnk:role name="test_wsdlProvider">
<plnk:portType name="tns:test_wsdl"/>
</plnk:role>
</plnk:partnerLinkType>
</definitions>

Проверяем wsdl программкой взятой с родного сайта: Interoperability Testing Tools 1.1

Assertion: BP2120
Failure Detail Message
getdata1,
getdata2
Element Location: lineNumber=96

В логе видим, что пункт "BP2120" не выполнен. Ошибка вот в этой строке:

<binding name="test_wsdlBinding" type="tns:test_wsdl">

Читаем про это: Test Assertion: BP2120
Хм, в байдинге не уникальные операции. Читаем дальше требования:
R2710

4.7.6 Operation Signatures

Definition: operation signature

The profile defines the "operation signature" to be the fully qualified name of the child element of SOAP body of the SOAP input message described by an operation in a WSDL binding.

In the case of rpc-literal binding, the operation name is used as a wrapper for the part accessors. In the document-literal case, since a wrapper with the operation name is not present, the message signatures must be correctly designed so that they meet this requirement.

An endpoint that supports multiple operations must unambiguously identify the operation being invoked based on the input message that it receives. This is only possible if all the operations specified in the wsdl:binding associated with an endpoint have a unique operation signature.

R2710The operations in a wsdl:binding in a DESCRIPTION MUST result in operation signatures that are different from one another.


Оказывается все просто. Точка входа (вызова) должна быть однозначно определена, в нашем случае part и element одинаковые для операций getdata1 и getdata2.

<message name="test_wsdl_getdata1RequestMessage">
<part name="payload" element="ns1:Request"/>
</message>

<message name="test_wsdl_getdata2RequestMessage">
<part name="payload" element="ns1:Request"/>
</message>

Изменеяем схему, добавляем новый элемент Request2, копию Request1 и используем его.

<message name="test_wsdl_getdata1RequestMessage">
<part name="payload" element="ns1:Request"/>
</message>
<message name="test_wsdl_getdata2RequestMessage">
<part name="payload" element="ns1:Request2"/>
</message>
Читать полностью

, , ,

Как получить userName из WS-Security soap-заголовка

четверг, 22 января 2009 г. 0 коммент.

Иногда в BPEL-процессе необходимо знать, какой пользователь вызвал этот web-сервис. Хорошо, когда имя пользователя передается в структуре сообщения, но когда имя пользователя необходимо получить из заголовка soap-сообщенини, то возникают небольшие трудности. Дело осложняется, если сервис защищен, например OWSM, с авторизацией в каком-нибудь LDAP-каталоге. Посмотрим как их можно решить.

Посмотрим на рисунок.



В этом "PipeLine" выполняются шаги по извлечению информации для авторизации "Extract Credentials", аутентификации "Ldap Authenticate" и авторизации "Ldap Authorize".
После выполнения шага "Extract Credentials" из сообщения удаляется информация о пользователе и пароле, поэтому чтобы получить необходимую информацию, добавим шаг "XML Transform", где укажем свою xsl-трансформацию.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:ns1="http://xmlns.oracle.com/test_soap"
version="1.0" >
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:input">
<xsl:element name="{name()}">
<xsl:value-of select="/soap:Envelope/soap:Header/wsse:Security/wsse:UsernameToken/wsse:Username"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

Трансформация копирует сообщение один в один за исключением одного элемента "ns1:input", в этом элемент мы копируем имя пользователя. Читать полностью