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

четверг, 1 марта 2018 г.

Ошибка "sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target" и вариант её решения

Ошибка:
После включения HTTPS (и отключения HTTP) может возникнуть следующая ошибка:
 <oracle.soa.bpel.engine.ws> <BEA-000000> <got FabricInvocationException  
 sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
     at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)  
     at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)  
     at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)  
     at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)  
     at sun.security.validator.Validator.validate(Validator.java:260)  
     at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)  
     at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)  
     at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)  
     at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1454)  
     at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:213)  
     at sun.security.ssl.Handshaker.processLoop(Handshaker.java:913)  
     at sun.security.ssl.Handshaker.process_record(Handshaker.java:849)  
     at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1035)  
     at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1344)  
     at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:721)  
     at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)  
     at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:167)  
     at HTTPClient.HTTPConnection.sendRequest(HTTPConnection.java:3398)  
     at HTTPClient.HTTPConnection.handleRequest(HTTPConnection.java:3310)  
     at HTTPClient.HTTPConnection$10.run(HTTPConnection.java:3061)  
     at HTTPClient.HTTPConnection$10.run(HTTPConnection.java:3052)  
     at HTTPClient.HttpClientConfiguration.doAction(HttpClientConfiguration.java:708)  
     at HTTPClient.HTTPConnection.doAction(HTTPConnection.java:5497)  
     at HTTPClient.HTTPConnection.setupRequest(HTTPConnection.java:3052)  
     at HTTPClient.HTTPConnection.Get(HTTPConnection.java:927)  
     at HTTPClient.HTTPConnection.Get(HTTPConnection.java:831)  
     at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.openAsStreamConnection(WSDLReaderImpl.java:548)  
     at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readDocument(WSDLReaderImpl.java:438)  
     at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:377)  
     at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:627)  
     at oracle.j2ee.ws.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:605)  
     at oracle.j2ee.ws.common.jaxws.WSDLMetadata.readWsdlDefinition(WSDLMetadata.java:377)  
     at oracle.j2ee.ws.common.jaxws.WSDLMetadata.initPortsFromWsdl(WSDLMetadata.java:202)  
     at oracle.j2ee.ws.common.jaxws.WSDLMetadata.initPorts(WSDLMetadata.java:171)  
     at oracle.j2ee.ws.common.jaxws.WSDLMetadata.getPort(WSDLMetadata.java:444)  
     at oracle.j2ee.ws.common.jaxws.ServiceDelegateImpl.createDispatch(ServiceDelegateImpl.java:275)  
     at javax.xml.ws.Service.createDispatch(Service.java:352)  
     at oracle.integration.platform.blocks.soap.AbstractWebServiceBindingComponent.dispatchRequest(AbstractWebServiceBindingComponent.java:558)  
     at oracle.integration.platform.blocks.soap.WebServiceExternalBindingComponent.processOutboundMessage(WebServiceExternalBindingComponent.java:314)  
     at oracle.integration.platform.blocks.soap.WebServiceExternalBindingComponent.sendSOAPMessage(WebServiceExternalBindingComponent.java:1230)  
     at oracle.integration.platform.blocks.soap.WebServiceExternalBindingComponent.request(WebServiceExternalBindingComponent.java:815)  
     at oracle.integration.platform.blocks.mesh.SynchronousMessageHandler.doRequest(SynchronousMessageHandler.java:139)  
     at oracle.integration.platform.blocks.mesh.MessageRouter.request(MessageRouter.java:182)  
     at oracle.integration.platform.blocks.mesh.MeshImpl.request(MeshImpl.java:190)  
     at sun.reflect.GeneratedMethodAccessor1787.invoke(Unknown Source)  
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
     at java.lang.reflect.Method.invoke(Method.java:606)  
     at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)  
     at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)  
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)  
     at oracle.integration.platform.metrics.PhaseEventAspect.invoke(PhaseEventAspect.java:71)  
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)  
     at com.sun.proxy.$Proxy390.request(Unknown Source)  
     at oracle.fabric.CubeServiceEngine.requestToMesh(CubeServiceEngine.java:859)  
     at com.collaxa.cube.ws.WSInvocationManager.invoke(WSInvocationManager.java:279)  
     at com.collaxa.cube.engine.ext.common.InvokeHandler.__invoke(InvokeHandler.java:1131)  
     at com.collaxa.cube.engine.ext.common.InvokeHandler.handleNormalInvoke(InvokeHandler.java:626)  
     at com.collaxa.cube.engine.ext.common.InvokeHandler.handle(InvokeHandler.java:131)  
     at com.collaxa.cube.engine.ext.bpel.common.wmp.BPELInvokeWMP.__executeStatements(BPELInvokeWMP.java:74)  
     at com.collaxa.cube.engine.ext.bpel.common.wmp.BaseBPELActivityWMP.perform(BaseBPELActivityWMP.java:173)  
     at com.collaxa.cube.engine.CubeEngine.performActivity(CubeEngine.java:2721)  
     at com.collaxa.cube.engine.CubeEngine._handleWorkItem(CubeEngine.java:1197)  
     at com.collaxa.cube.engine.CubeEngine.handleWorkItem(CubeEngine.java:1100)  
     at com.collaxa.cube.engine.dispatch.message.instance.PerformMessageHandler.handleLocal(PerformMessageHandler.java:76)  
     at com.collaxa.cube.engine.dispatch.DispatchHelper.handleLocalMessage(DispatchHelper.java:251)  
     at com.collaxa.cube.engine.dispatch.DispatchHelper.sendMemory(DispatchHelper.java:330)  
     at com.collaxa.cube.engine.CubeEngine.endRequest(CubeEngine.java:4653)  
     at com.collaxa.cube.engine.CubeEngine.endRequest(CubeEngine.java:4584)  
     at com.collaxa.cube.engine.CubeEngine._createAndInvoke(CubeEngine.java:714)  
     at com.collaxa.cube.engine.CubeEngine.createAndInvoke(CubeEngine.java:559)  
     at com.collaxa.cube.engine.delivery.DeliveryService.handleInvoke(DeliveryService.java:535)  
     at com.collaxa.cube.engine.ejb.impl.CubeDeliveryBean.handleInvoke(CubeDeliveryBean.java:319)  
     at sun.reflect.GeneratedMethodAccessor2242.invoke(Unknown Source)  
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
     at java.lang.reflect.Method.invoke(Method.java:606)  
     at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)  
     at com.oracle.pitchfork.intercept.MethodInvocationInvocationContext.proceed(MethodInvocationInvocationContext.java:103)  
     at oracle.security.jps.ee.ejb.JpsAbsInterceptor$1.run(JpsAbsInterceptor.java:113)  
     at java.security.AccessController.doPrivileged(Native Method)  
     at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:324)  
     at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:460)  
     at oracle.security.jps.ee.ejb.JpsAbsInterceptor.runJaasMode(JpsAbsInterceptor.java:100)  
     at oracle.security.jps.ee.ejb.JpsAbsInterceptor.intercept(JpsAbsInterceptor.java:154)  
     at oracle.security.jps.ee.ejb.JpsInterceptor.intercept(JpsInterceptor.java:113)  
     at sun.reflect.GeneratedMethodAccessor1196.invoke(Unknown Source)  
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
     at java.lang.reflect.Method.invoke(Method.java:606)  
     at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)  
     at com.oracle.pitchfork.intercept.JeeInterceptorInterceptor.invoke(JeeInterceptorInterceptor.java:68)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)  
     at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at com.oracle.pitchfork.spi.MethodInvocationVisitorImpl.visit(MethodInvocationVisitorImpl.java:34)  
     at weblogic.ejb.container.injection.EnvironmentInterceptorCallbackImpl.callback(EnvironmentInterceptorCallbackImpl.java:54)  
     at com.oracle.pitchfork.spi.EnvironmentInterceptor.invoke(EnvironmentInterceptor.java:42)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at com.bea.core.repackaged.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)  
     at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)  
     at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
     at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)  
     at com.sun.proxy.$Proxy371.handleInvoke(Unknown Source)  
     at com.collaxa.cube.engine.ejb.impl.bpel.BPELDeliveryBean_5k948i_ICubeDeliveryLocalBeanImpl.__WL_invoke(Unknown Source)  
     at weblogic.ejb.container.internal.SessionLocalMethodInvoker.invoke(SessionLocalMethodInvoker.java:39)  
     at com.collaxa.cube.engine.ejb.impl.bpel.BPELDeliveryBean_5k948i_ICubeDeliveryLocalBeanImpl.handleInvoke(Unknown Source)  
     at com.collaxa.cube.engine.dispatch.message.invoke.InvokeInstanceMessageHandler.handle(InvokeInstanceMessageHandler.java:30)  
     at com.collaxa.cube.engine.dispatch.DispatchHelper.handleMessage(DispatchHelper.java:141)  
     at com.collaxa.cube.engine.dispatch.BaseDispatchTask.process(BaseDispatchTask.java:89)  
     at com.collaxa.cube.engine.dispatch.BaseDispatchTask.run(BaseDispatchTask.java:65)  
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
     at com.collaxa.cube.engine.dispatch.Dispatcher$ContextCapturingThreadFactory$2.run(Dispatcher.java:933)  
     at java.lang.Thread.run(Thread.java:745)  
 >  

Причина:
Не до конца завершена конфигурация HTTPS (TLS).

Вариант решения:
Необходимо добавить в параметры старта Weblogic-серверов следующие свойства:
 -Djavax.net.ssl.trustStoreType=JKS  
 -Djavax.net.ssl.trustStorePassword=XXXXX  

среда, 30 декабря 2015 г.

Пользовательские задачи Oracle BPM 12c: роли и подразделения пользователей

Участником задачи могут быть:
  • пользователь (user);
  • группа пользователей (group);
  • роль пользователей (app.role), в контексте Oracle BPM.
Взаимосвязь между участниками указана ниже:

Орг.единицы (Organization Unit) определяют структуру организации, например:

Важно отметить, что орг.единицы логически связанны только с ролями пользователей (т.е. не для группы пользователей и тем более не для пользователя).

Рассмотрим на примере как работает механизм орг.единиц:

В соответствии со схемой выше, в организации есть 3 бухгалтера по одному в каждом отделении и аналогично 3 инженера в каждом отделении.
Создадим две роли "Бухгалтер" и "Инженер" и три орг.подразделения и добавим в них соответствующих сотрудников. Таким образом получается:
Роль
Пользователь
Организационное подразделение
Бухгалтер
Иванова
Западносибирское отд.
Сидирова
Уральское отделение
Кузнецова
Дальневосточное отд.
Инженер
Петрова
Западносибирское отд.
Алексеева
Уральское отделение
Борисова
Дальневосточное отд.

Создадим простейший BPMN-процесс с одной задачей:

Но данная задача должна назначаться на роль "Бухгалтер" уральского подразделения, для этого добавляем перед назначением задачи добавим script-активность, в которой укажем необходимое орг.подразделение (Process / Predefined Variables / Organization Unit):
Если бы мы не указали орг.подразделение, то задача назначилась на всех участников роли "Бухгалтер", т.е. доступ был бы у 3-х сотредников. 
Так как мы указали орг.подразделение, то задача назначится на того сотрудника роли "Бухгалтер", который входит в указанное подразделение, т.е. Сидорову.

Данная функциональность позволяет сильно сократить количество ролей (без неё потребовалось бы 6 ролей вместо 2).

воскресенье, 8 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: пример реализации ограничения перечня пользователей для операции "Делегирование"

По умолчанию задачу в Oracle BPM можно переназначить или делегировать на любого пользователя, роль и группу. Но можно ограничить этот перечень создав класс в BPM-проекте (в терминах JDeveloper), который реализует интерфейс oracle.bpel.services.workflow.task.IRestrictedAssignmentCallback.

Рассмотрим пример в котором нужно ограничить перечень пользователей для операции "Делегирование" следующим образом:
  • Если исполнителем задачи является группа или роль, то делегировать можно только пользователям из состава этой группы или роли;
  • Если исполнителем задачи является пользователь, то делегировать нельзя (пустой перечень доступных для делегирования пользователей).
Пример кода:
 import java.util.ArrayList;  
 import java.util.Collections;  
 import java.util.List;  
 import java.util.Map;  
   
 import oracle.bpel.services.workflow.IWorkflowConstants;  
 import oracle.bpel.services.workflow.task.IRestrictedAssignees;  
 import oracle.bpel.services.workflow.task.IRestrictedAssignmentCallback;  
 import oracle.bpel.services.workflow.task.impl.RestrictedAssignees;  
 import oracle.bpel.services.workflow.task.impl.TaskAssignee;  
 import oracle.bpel.services.workflow.task.model.Task;  
   
 import oracle.tip.pc.services.common.ServiceFactory;  
 import oracle.tip.pc.services.identity.BPMAppRole;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
 import oracle.tip.pc.services.identity.BPMGroup;  
 import oracle.tip.pc.services.identity.BPMIdentityService;  
 import oracle.tip.pc.services.identity.BPMUser;  
   
 import oracle.bpel.services.workflow.task.model.IdentityType;  
   
 public class RestrictedAssignmentCallbackImpl implements IRestrictedAssignmentCallback {  
   
   public IRestrictedAssignees getPermittedAssignees(Task task, Map map, String currentUser, String identityContext,  
                            String operation) {  
     List assignees = new ArrayList();  
     if (operation.equals(IRestrictedAssignmentCallback.OperationType.REASSIGN.toString())) {  
       //TODO реализовать логику для операции "Переназначение"  
     } else if (operation.equals(IRestrictedAssignmentCallback.OperationType.DELEGATE.toString())) {  
       try {  
         BPMIdentityService idenService = getIdentityServiceInstance(identityContext);  
         List<IdentityType> assigneesList = task.getSystemAttributes().getAssignees();  
         for (IdentityType assignee : assigneesList) {  
           if (IWorkflowConstants.IDENTITY_TYPE_GROUP.equals(assignee.getType())) {  
             List<BPMUser> usersInGroup =  
               idenService.getParticipantsToGroup(assignee.getDisplayName(), true);  
             for (BPMUser user : usersInGroup) {  
               assignees.add(new TaskAssignee(user.getName(), IWorkflowConstants.IDENTITY_TYPE_USER));  
             }  
           } else if (IWorkflowConstants.IDENTITY_TYPE_APPLICATION_ROLE.equals(assignee.getType())) {  
             List<BPMUser> usersInGroup =  
               idenService.getParticipantsToAppRole(assignee.getDisplayName(),  
                                  task.getApplicationContext(), false);  
             for (BPMUser user : usersInGroup) {  
               assignees.add(new TaskAssignee(user.getName(), IWorkflowConstants.IDENTITY_TYPE_USER));  
             }  
           } else if (IWorkflowConstants.IDENTITY_TYPE_USER.equals(assignee.getType())) {  
             // Пустой список  
             return new RestrictedAssignees(new ArrayList(), true);  
           }  
         }  
   
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     }   
   
     if (!assignees.isEmpty()) {  
       return new RestrictedAssignees(assignees, true);  
     }  
   
     return null;  
   }  
   
   public List<IRestrictedAssignmentCallback.OperationType> getRestrictedOperations(Task task, Map map,  
                                            String currentUser,  
                                            String identityContext) {  
     return Collections.emptyList();  
   }  
   
   private BPMAuthorizationService getAuthorizationService(String realmName) {  
     return ServiceFactory.getAuthorizationServiceInstance(realmName);  
   }  
   
   private BPMIdentityService getIdentityServiceInstance(String realmName) {  
     return ServiceFactory.getIdentityServiceInstance(realmName);  
   }  
 }  
   

суббота, 7 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: Custom Escalation Java Function

Custom Escalation Java Function указывается в конфигурации задачи для указания по какой логике будет выполняться эскалация для пользователей и групп (для ролей не используется!).

Custom Escalation Java Function рассмотрим на примере:
 package oracle.bpel.services.workflow.assignment.dynamic;  
   
 import java.util.List;  
 import java.util.Map;  
   
 import oracle.bpel.services.workflow.task.model.Task;  
 import oracle.bpel.services.workflow.assignment.dynamic.DynamicAssignmentException;  
   
 import oracle.tip.pc.services.common.ServiceFactory;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
   
 import oracle.tip.pc.services.identity.BPMAppRole;  
 import oracle.tip.pc.services.identity.BPMAuthorizationService;  
 import oracle.tip.pc.services.identity.BPMGroup;  
 import oracle.tip.pc.services.identity.BPMIdentityService;  
 import oracle.tip.pc.services.identity.BPMUser;  
 /*  
  * Обеспечивает эскалацию на владельца задачи.  
  */  
 public class OwnerEscalation implements IDynamicTaskEscalationFunction {  
   public String defaultUser;  
   
   @Override  
   public String getTaskEscalationUser(Task task) throws DynamicAssignmentException {  
     String ownerRole = task.getOwnerRole();  
     String ownerGroup = task.getOwnerGroup();  
     String ownerUser = task.getOwnerUser();  
     if (ownerRole != null) {  
       try {  
         BPMAuthorizationService idenService = ServiceFactory.getIdentityServiceInstance();  
         List<BPMUser> usersInRole =  
           idenService.getParticipantsToAppRole(ownerRole, task.getApplicationContext(), false);  
         if (usersInRole.size() > 0) {  
           // Берём первого пользователя  
           return usersInRole.get(0).getName();  
         }  
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     } else if (ownerGroup != null) {  
       try {  
         BPMAuthorizationService idenService = ServiceFactory.getIdentityServiceInstance();  
         List<BPMUser> usersInGroup = idenService.getParticipantsToGroup(ownerGroup, true);  
         if (usersInGroup.size() > 0) {  
           // Берём первого пользователя  
           return usersInGroup.get(0).getName();  
         }  
       } catch (Exception ex) {  
         ex.printStackTrace();  
       }  
     } else if (ownerUser != null) {  
       return ownerUser;  
     }  
     return defaultUser;  
   }  
   
   @Override  
   public String getTaskEscalationUser(String string) throws DynamicAssignmentException {  
     return defaultUser;  
   }  
   
   @Override  
   public void setInitParams(Map map) throws DynamicAssignmentException {  
     // Добавляем параметр указывающий на какого пользователя проводить эскалацию,   
     // если владелец задачи (Owner) не указан  
     defaultUser=(String)map.get("DEFAULT_USER");  
   }  
   
   @Override  
   public String getFunctionName() {  
     return "OWNER_ESCALATION";  
   }  
   
   @Override  
   public String getDescription() {  
     return "Escalation to task owner";  
   }  
 }  
   
Логика данного примера:
Если у задачи определён владелец (Owner), то эскалация будет выполняться на владельца. Иначе, на пользователя указанного в конфигурации как DEFAULT_USER

Важно:

  • Класс должен быть в пакете oracle.bpel.services.workflow.assignment.dynamic.

Установка:

  1. Собрать JAR содержащий класс и положить его в директорию $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1
  2. Запустить ant в директории $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1 (вероятно потребуется проинициализировать переменные окружения)
  3. Перезагрузить soa-сервер для того, чтобы новый класс был доступен серверу (был в classpath).
  4. Зарегистрировать Task Escalation Function:
    1. Войти в EM (Enterprise Manager Fusion Middleware Control)
    2. Перейти в soa-infra -> SOA Administration -> Workflow Properties
    3. Перейти на закладку Task и добавить наш класс (Add function) следующим образом:
Альтернативный вариант: вместо указанных действий в п.1-2 можно положить скомпилированный класс в директорию $MW_HOME\soa\soa\modules\oracle.soa.ext_11.1.1\classes

вторник, 3 ноября 2015 г.

Пользовательские задачи Oracle BPM 12c: новая функциональность таймеров

После авторизации в Oracle BPM Workspace 12c выбрав экземпляр любой задачи вы обнаружите, что у задач появились два новых действия:
  • Начать работу (Start Task)
  • Закончить работу (Stop Task)
Функциональность данных действий работает следующим образом:
После выполнения "Начать работу" включается таймер, а после выполнения "Закончить работу" таймер выключается и сохраняется длительность включённого таймера с нарастающим итогом

Особенности

  • Функциональность "Начать работу" / "Закончить работу" не генерируют событий (EDN), поэтому значения можно узнать через API или в следующем (по времени) генерируемом событии.
  • Если задача назначена на группу/роль, то выполнение "Начать работу" приводит так же к выполнению "Взять в работу".
  • Если пользователь выполнил "Начать работу" и затем исполнил/завершил задачу (т.е. не была выполнена операция "Закончить работу"), то значение таймера длительности будет 0. 
  • Таймер никак не связан с пользователями выполняющими действия. Последовательный пример: 
    1. назначается задача на первого пользователя
    2. первый пользователь выполняет "Начать работу"
    3. первый пользователь переназначает на второго пользователя
    4. второй пользователь выполняет "Закончить работу" и исполняет/завершает задача
    В итоге: нет информации сколько времени с задачей работал первый пользователь, а сколько второй. Есть только информация сколько времени прошло с включения таймера (действия "Начать работу") до выключения таймера (действия "Закончить работу").

Недостатки

  • Данная функциональность не документирована (ни в пользовательской документации, ни в Oracle Fusion Middleware Workflow Services Java API Reference for Oracle SOA Suite).
  • Следствие первого пункта - доступна только из Oracle BPM Workspace 12c (как следствие, не доступна, если вы не используете его).
  • Следствие первого пункта - данная функциональность может быть изменена вендором (пока не будет внесена в публичную документацию). 

суббота, 31 октября 2015 г.

Пользовательские задачи Oracle BPM 12c: эскалация

Под эскалацией в Oracle BPM 12c (и в 11g) подразумевается автоматическое переназначение исполнителя задачи на другую роль, группу или пользователя (обычно более высокого по иерархии).

Эскалация может производиться:
  • автоматически по истечению указанного времени в конфигурации задачи
  • пользователем выполнившим действие «Эскалировать» (Escalate), которое может быть доступно:
    • Исполнителю задачи (Assignee)
    • Владельцу задачи (Owner)
    • Администратору (Admin)

Особенности:

  • В зависимости от того на ком находится задача на момент эскалации:
    • Если это группа или пользователь, то отрабатывает указанная custom escalation java function (если функция не указана, то задача завершится будет ошибкой)
    • Если это роль, то выполняется эскалация на указанный в роли Escalation Path (может быть роль, группа, пользователь).
       
    • Последующие эскалации:
      • Если в Escalation Path указана роль, то последующая эскалация будет выполнятся на Escalation Path данной роли
      • Если в Escalation Path указан пользователь или группа, то отрабатывает указанная custom escalation java function (если функция не указана, то задача завершится будет ошибкой).
  • Для каждой задачи можно задать глубину автоматической эскалации, т.е. кол-во раз которое будет выполнятся эскалация. По истечению указанного количества задача становится просроченной (expired).

четверг, 4 июня 2015 г.

Декодирование xsd:base64Binary в xsd:string

Цель:
При использовании JMS Adapter для получения текстового сообщения в формате XML, для которого XSD не известна, используется опция "Native format translation is not required (Schema is Opaque)". В этом случае входящее сообщение будет содержать элемент типа xsd:base64Binary, содержащий закодированное в base64 полученное сообщение.
Решение:
Т.к. в Oracle SOA Suite 11g отсутствует XSLT или XPATH-функции, позволяющая декодировать base64, поэтому можно использовать активность "Java Embedding" для решения данной задачи.
Итак, в BPEL-процессе есть две переменные:
 <!-- входная переменная из JMS Adapter -->
 <variable name="encoded_Input" messageType="ns1:Consume_Message_msg"/>  
 <!-- переменная в которую декодируем base64 -->
 <variable name="decoded_Input" type="xsd:string"/>
Добавляем в BPEL-процесс активность "Java Embedding" содержащую следующий код:
 try {      
     oracle.xml.parser.v2.XMLElement input = (oracle.xml.parser.v2.XMLElement) getVariableData("encoded_Input", "opaque");
     String input_str = input.getTextContent();   
     oracle.soa.common.util.Base64Decoder decoder = new oracle.soa.common.util.Base64Decoder();        
     String decoded = null;       
     decoded = decoder.decode(input_str);   
     setVariableData("decoded_Input", decoded);      
 } catch (Exception e) {  
     addAuditTrailEntry("EXCEPTION OCCURRED: " + e.toString());  
 }  

Альтернативный вариант - создание собственной XSLT или XPATH-функции для декодирования base64.

четверг, 16 апреля 2015 г.

Освоение Oracle BPM

Требуется:
Выполнить простейший tutorial с Oracle Technology NetworkДалее выполнить tutorial по одной из следующих книг:
  • Getting Started with Oracle BPM Suite 11gR1
  • Oracle BPM Suite 11g Developer's Cookbook
Изучить "продвинутые" аспекты по книге: 
  • Oracle BPM Suite 11g Advanced BPMN Topics
Полезные ссылки:

суббота, 4 октября 2014 г.

Пятая часть освоения SOA

Требуется изучить:

Выполнить задание:

  • Сенсоры и BAM:
    • По книге Getting Started With Oracle SOA Suite 11gR1 изучить и выполнить задания по главе 16 (посвящённой Oracle BAM);
    • Сделать композит (с BPEL-процессом), который будет вызывать внешний сервис (который нужно так же реализовать). Этот внешний сервис периодически возвращает ошибку (например такая логика: если минута в текущем времени четная, то вернуть ошибку). Нужно сделать отчёт средствами Oracle BAM содержащий информацию по общему кол-ву запущенных инстансов и сколько из них с ошибками
  • REST:
    • Сделать композит взаимодействующий с RESTful-сервисом (сам RESTful-сервис создайте его любым удобным средством).

пятница, 3 октября 2014 г.

Четвертая часть освоения SOA

Требуется изучить:


Выполнить задание:

  • MDS: задеплоить в MDS артефакты (XSD, WSDL, fault policy file) и сделать простой композит использующий данные артефакты.
  • Resequencing: сделать композит иллюстрирующий работу  всех вариантов Resequencing – Standard, FIFO, Best effort.
  • EDN
    • Сделать композит с WS-интерфейсом, который генерирует событие (EDN), а другой композит слушает это событие и записывает информацию в БД. 
    • Сделать отдельный композит который слушает события от HumanTask (в качестве композита с HumanTask предлагаю взять таковой из tutorial) и записать информацию (как минимум: идентификатор задачи, кто сделал (логина достаточно), что сделал (действие) и когда сделал(время)) в БД

четверг, 2 октября 2014 г.

Третья часть освоение SOA

Выполнить задания:

  • Задачка 1
Сделать композит, который периодически опрашивает (polling) таблицу БД на наличие строк со статусом READY и при их появлении пишет в файловую директорию cvs-файлы.

  • Задачка 2

Сделать композит, который периодически опрашивает (polling) файловую директорию на наличие csv-файлов следующей структуры:
First name,Last name,ID,E-mail
John,Doe,01234567,john.doe@domain.com
Alex,Smith,88888888,alex.smith@domain.com
Необходимо записать данные из csv-файлов в таблицу БД (сделать табличку с теми же полями и первичный ключ по всем полям). 

  • Задачка 3

Сделать композит, который «слушает» очереди JMS и AQ (т.е. две очереди; внутри XML-сообщения) и записывает данные сообщения в таблицу БД через вызов API-процедуры.

  • Задачка 4

Добавить в существующий композит (см. задачку 2) дополнительную операцию (интерфейс WS), входная переменная которой получает полный путь к локальному csv-файлу (структура та же).  Необходимо записать данные из указанного файла в таблицу БД.

  • Задачка 5

Добавить обработку ошибок в композите (см. задачку 2)  и в случае ошибки вставки в таблицу БД (ошибка по первичному ключу) переводить на администратора (humanIntervention), который может изменить значения полей и завершить выполнение композита

среда, 1 октября 2014 г.

Вторая часть освоения SOA

Требуется изучить:

Выполнить tutorial. Есть следующие полезные книги:
  • Getting Started With Oracle SOA Suite 11gR1 (главы 1-10,13-15,17)
  • Oracle SOA Suite 11g R1 Developers Guide (главы 1-8,11,13-14,18-21)
  • WS-BPEL 2.0 for SOA Composite Applications with Oracle SOA Suite 11g (главы 1-7 включительно)
Книги однотипные, главы связанные с BAM (Business Activity Monitorung) и OSB (Oracle Service Bus) пока не рассматриваем. Первые две книги содержат tutorial-ы. Пройдите от начала до конца одину из них (см. указанные главы). Обрати внимание, что оба tutorial-а по немного более старой версии SOA (например по 11.1.1.5), хотя на данный момент чаще всего используется версии 11.1.1.6 и 11.1.1.7 - поэтому скриншоты в книгах могут немного не совпадать.
После завершения tutorial просмотреть остальные книги на непроработанный/незатронутый функционал.

Выполнить задание:

  1. Создать две JMS Queue в Weblogic;
  2. Создать MDB, который перекладывает сообщения из одной очереди в другую;
  3. Развернуть на сервере и протестировать.

Полезные ссылки:

  1. Рекомендую использовать официальный developers guide по Oracle SOA, как справочник.
  2. Хороший блог по Oracle SOA на русском языке
  3. Блоги на английском:

вторник, 30 сентября 2014 г.

Первая часть освоения SOA

Требуется изучить:

Книг по XML много, в том числе и на русском. Дополнительно полезно знать XQuery. Нужно понимание функциональности и возможностей XQuery по сравнению с XSL. Рекомендую книгу «W3C XML: Xquery от экспертов. Руководство по языку запросов» или в оригинале «XQuery from the Experts: A Guide to the W3C XML Query Language».

  • Weblogic. Требуется разобраться:
    • Как минимум, в следующих технологиях:
      • JMS (Java Message Service)
      • MDB (Message Driven Bean)
      • JTA & JTS (Java Transaction API & Java Transaction Service)
    • В основах администрирования.

Полезные ссылки:

Освоение Oracle SOA

За основу данного набора статей взята моя переписка с начинающими разработчиками SOA, целью которой было вырастить разработчиков Oracle SOA Suite. Кроме переписки было обсуждение вопросов и задач через Skype. Формат следующий:

  • Что нужно изучить с ссылками на материалы;
  • Простейшие практические задачки;
  • Полезные ссылки.

Обращаю внимание, что этот набор статей не охватывает весь функционал Oracle SOA Suite, а включает только наиболее часто используемый функционал. Так же смотрите на полезные ссылки в постах пройдя по которым можно изучить неохваченный функционал.

Этот пост подержит ссылки на все посты из данного набора:

P.S. рекомендации приветствуются J

понедельник, 29 сентября 2014 г.

Список необходимых патчей для Oracle SOA & BPM Suite 11g PS6 (11.1.1.7)

Перечень патчей которые необходимо развернуть для Oracle SOA & BPM Suite 11g PS6 (11.1.1.7):
  • Patch 17294404: XSDCOMPLEXTYPE.GETCHILDELEMENTS() IS NOT THREAD SAFE
  • Patch 18325165: MERGE REQUEST ON TOP OF 11.1.1.7.0 FOR BUGS 16319620 16487002
  • Patch 18609527: SOA BUNDLE PATCH 11.1.1.7.4
  • Patch 18366461: NULLPOINTEREXCEPTION AT WEBSERVICEEXTERNALBINDINGCOMPONENT.GETINVOCATIONMETADATA
Скачать эти патчи можно c support.oracle.com.

P.S. список патчей будет дополняться (при необходимости).
P.P.S. рекомендации по патчам приветствуются :-)

понедельник, 13 января 2014 г.

SoapUI: подстановка вычисляемых значений с помощью вставок на Groovy

Целей функционального тестирования композитных приложений иногда используются заглушки и/или SoapUI,EM и прочие средства. Но как правило необходимо отправлять сообщения с отличающимися данными, например: документ на согласование с различными идентификатором и текущей датой отправки. Можно каждый раз перед отправкой менять значения вручную, но удобнее например для числовых идентификаторов использовать случайное число из определённого диапазона, а для даты подставлять например текущую дату. В SoapUI есть поддержка Groovy и подобное поведение делается очень легко (выделено красным):
Итак, в качестве значения поля для генерации:
  • числового значения в диапазоне от 0 до 10000 нужно подставить:
     ${=(int)(Math.random()*10000)}  
    
  • текущей даты нужно подставить:
     ${=new Date().format(‘yyyy-MM-dd’)}  
    

пятница, 8 ноября 2013 г.

Oracle SOA: управление композитами через WLST

Все команды выполняются из wlst.cmd или wlst.sh находящегося в SOA_HOME, у меня например это:
 C:\Apps\Oracle\Weblogic\10.3.6\Oracle_SOA1\common\bin\wlst.cmd  
  • Просмотр развёрнутых композитов и их статусов:
    wls:/offline> 
     sca_listDeployedComposites('bpm-dev.mycompany.com',
                                '8001',
                                'weblogic',
                                'welcome1') 
    
    где weblogic - логин административного пользователя;
    welcome1 - пароль административного пользователя;
    bpm-dev.mycompany.com - хост SOA-сервера;
    8001 - порт SOA-сервера.

    Пример результата:
     Following 4 composites are currently deployed to the platform:  
     1. AsyncProc[1.0], partition=default, mode=active, state=on, isDefault=true, deployedTime=2013-07-25T11:26:03.309+04:00  
     2. SimpleApproval[1.0], partition=default, mode=active, state=on, isDefault=true, deployedTime=2012-10-17T18:55:11.333+04:00  
     3. SimpleHT[1.0], partition=default, mode=active, state=on, isDefault=true, deployedTime=2012-12-21T13:23:24.345+04:00  
     4. AgreementApproversService[1.0], partition=prod, mode=active, state=on, isDefault=true, deployedTime=2013-02-22T17:51:30.971+04:00  
    
  • Старт композита:
    wls:/offline> 
     sca_startComposite('bpm-dev.mycompany.com',
                        '8001',
                        'weblogic',
                        'welcome1',
                        'AsyncProc',
                        '1.0',
                        partition='default') 
    
    где AsyncProc - имя композита;
    1.0 - версия композита;
    default - раздел.

  • Стоп композита:
    wls:/offline> 
     sca_stopComposite('bpm-dev.mycompany.com',
                       '8001',
                       'weblogic',
                       'welcome1',
                       'AsyncProc',
                       '1.0',
                       partition='default') 
    
  • Активация композита:
    wls:/offline> 
     sca_activateComposite('bpm-dev.mycompany.com',
                           '8001',
                           'weblogic',
                           'welcome1',
                           'AsyncProc',
                           '1.0',
                           partition='default') 
    
  • Деактивация композита:
    wls:/offline> 
     sca_retireComposite('bpm-dev.mycompany.com',
                         '8001',
                         'weblogic',
                         'welcome1',
                         'AsyncProc',
                         '1.0',
                         partition='default') 
    

четверг, 21 марта 2013 г.

Oracle SOA Poster-BPEL Process 2.0

Коллеги из EAIESB опубликовали BPEL 2.0 Poster (оригинал здесь):

понедельник, 17 сентября 2012 г.

Ошибка "internal xpath error" в oraext:query-database и вариант её решения

Ошибка:
При использовании XPath-функции oraext:query-database, если в запросе используются функции БД (например: select max(salary) from employee) возникает ошибка следующего вида:
 <bpelFault>  
  <faultType>0</faultType>  
  <subLanguageExecutionFault xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable">  
   <part name="summary">  
    <summary>An error occurs while processing the XPath expression; the  
         expression is oraext:query-database("select  
         max(salary) from employee",false(),false(),'jdbc/examplesDS').</summary>  
   </part>  
   <part name="detail">  
    <detail>XPath expression failed to execute. An error occurs while  
        processing the XPath expression; the expression is  
        oraext:query-database("select max(salary) from  
        employee",false(),false(),'jdbc/examplesDS'). The XPath  
        expression failed to execute; the reason was: internal xpath  
        error. Check the detailed root cause described in the exception  
        message text and verify that the XPath query is correct.</detail>  
   </part>  
   <part name="code">  
    <code>XPath expression failed to execute</code>  
   </part>  
  </subLanguageExecutionFault>  
 </bpelFault>  
А в логе managed-сервера:
 oracle.xml.sql.OracleXMLSQLException: Character ')' is not allowed in an XML tag name.  
     at oracle.xml.sql.core.OracleXMLConvert.getXML(OracleXMLConvert.java:1178)  
     at oracle.xml.sql.query.OracleXMLQuery.getXMLDOM(OracleXMLQuery.java:417)  
     at oracle.xml.sql.query.OracleXMLQuery.getXMLDOM(OracleXMLQuery.java:384)  
     at oracle.xml.sql.query.OracleXMLQuery.getXMLDOM(OracleXMLQuery.java:345)  
     at oracle.tip.pc.services.functions.ExtFunc.queryDatabase(ExtFunc.java:152)  
     at oracle.tip.pc.services.functions.ExtFuncFunction$QueryDatabaseFunction.call(ExtFuncFunction.java:359)
     ...
Причина:
XML SQL Utility (XSU) обрабатывает имя столбца как имя тега. В нашем случае имя столбца max(salary) рассматривается XSU как недопустимое имя тега, и происходит ошибка.

Вариант решения:
Необходимо добавить алиас для столбца в котором используются функции, т.е. в нашем случае:
 oraext:query-database("select max(salary) as salary from employee",
                                       false(),false(),'jdbc/examplesDS')  

воскресенье, 29 июля 2012 г.

Управление структурой MDS с помощью MDS Explorer

  MDS Explorer - это OpenSource-проект, цель которого создание средства для доступа к Oracle MDS (Meta Data Services) репозиториям с помощью которого можно создавать, удалять, загружать, выгружать директории и файлы.
  На сайте проекта можно скачать исходники (в скомпилированном виде отсутствуют). В скомпилированном виде в одном jar-файле выкладываю здесь.
  Запуск:
  1. Выполнить следующую команду:
     java -Drepository.flavor=DB -jar MDSExplorer.jar  
    
    где DB - для доступа к репозиторию в БД;
        FILE - для доступа к репозиторию в файловой системе.
  2. Ввести параметры соединения со схемой MDS, затем нажать "Connect", выбрать нужный раздел (partition) и нажать "OK":
  3. В открывшемся окне можно выполнять действия по управлению структурой MDS: