Sunday, March 8, 2015

Oracle BPM: Solving "The XID is not valid" exception

Recently i faced a strange exception while using the BPM server:
       

java.sql.SQLException: Unexpected exception while enlisting XAConnection java.sql.SQLException: XA error: XAResource.XAER_NOTA start() failed on resource 'SOADataSource_domain': XAER_NOTA : The XID is not valid oracle.jdbc.xa.OracleXAException at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1616)
       
 

In order to resolve this exception, you need to edit your Custom XA Datasource which your BPM processes use with the following attribute.
Enable "Set XA Transaction Timeout"


Restart you domain (Admin and SOA servers)

That's it.

Oracle BPM: Assign User to Application Role Programmatically

In order to assign users to application role programmatically in Oracle BPM, user the following code:

       


import java.util.HashMap;
import java.util.Map;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;
import oracle.bpel.services.workflow.verification.IWorkflowContext;

import oracle.bpm.client.BPMServiceClientFactory;
import oracle.bpm.services.organization.BPMOrganizationException;
import oracle.bpm.services.organization.model.ApplicationContext;
import oracle.bpm.services.organization.model.ApplicationContextTypeEnum;
import oracle.bpm.services.organization.model.ParticipantTypeEnum;
import oracle.bpm.services.organization.model.PrincipleRefType;
import oracle.bpm.workspace.util.WorkspaceUtil;

public class CustomWorklistUtils {
    public CustomWorklistUtils() {
        super();
    }
    private IBPMContext bpmContext = null;

    private static String adminUsername;
    private static String adminPassword;
    private static String bpmURL;


    public boolean createNewMember(String appRoleName, String member,
                                   String type) {
        System.out.println("Assigning User to ApplicationRole(Lane)...");
        System.out.println("...appRoleName: " + appRoleName);
        System.out.println("...member: " + member);
        System.out.println("...type: " + type);
        if (appRoleName == null) {
            return false;
        }

        PrincipleRefType principleRefType =
            WorkspaceUtil.getBPMObjectFactory().createPrincipleRefType();
        principleRefType.setName(member);
        principleRefType.setRealm(getBPMContext().getIdentityContext());

        if (type.equalsIgnoreCase(("LABEL_USER"))) {
            principleRefType.setType(ParticipantTypeEnum.USER);
        } else if (type.equalsIgnoreCase(("LABEL_GROUP"))) {
            principleRefType.setType(ParticipantTypeEnum.GROUP);
        } else if (type.equalsIgnoreCase(("LABEL_APPROLE"))) {
            principleRefType.setType(ParticipantTypeEnum.APPROLE);
        }

        ApplicationContext appContext =
            WorkspaceUtil.getBPMObjectFactory().createApplicationContext();
        appContext.setApplicationType(ApplicationContextTypeEnum.ORACLE_BPM_PROCESS_ROLES_APP);
        oracle.bpm.services.organization.model.Participant participant =
            WorkspaceUtil.getBPMObjectFactory().createParticipant(principleRefType);
        try {
            WorkspaceUtil.getBPMOrgUnitService().grantAppRoleToPrincipal(getBPMContext(),
                                                                         appContext,
                                                                         appRoleName,
                                                                         participant);

            return true;
        } catch (BPMOrganizationException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    public boolean removeMemberFromAppRole(String appRoleName, String member,
                                           String type) {
        if (appRoleName == null) {
            return false;
        }

        PrincipleRefType principleRefType =
            WorkspaceUtil.getBPMObjectFactory().createPrincipleRefType();
        principleRefType.setName(member);
        principleRefType.setRealm(getBPMContext().getIdentityContext());

        if (type.equalsIgnoreCase(("LABEL_USER"))) {
            principleRefType.setType(ParticipantTypeEnum.USER);
        } else if (type.equalsIgnoreCase(("LABEL_GROUP"))) {
            principleRefType.setType(ParticipantTypeEnum.GROUP);
        } else if (type.equalsIgnoreCase(("LABEL_APPROLE"))) {
            principleRefType.setType(ParticipantTypeEnum.APPROLE);
        }

        ApplicationContext appContext =
            WorkspaceUtil.getBPMObjectFactory().createApplicationContext();
        appContext.setApplicationType(ApplicationContextTypeEnum.ORACLE_BPM_PROCESS_ROLES_APP);
        oracle.bpm.services.organization.model.Participant participant;
        participant =
                WorkspaceUtil.getBPMObjectFactory().createParticipant(principleRefType);
        try {
            WorkspaceUtil.getBPMOrgUnitService().revokeAppRoleFromPrincipal(getBPMContext(),
                                                                            appContext,
                                                                            appRoleName,
                                                                            participant);

            return true;
        } catch (BPMOrganizationException ex) {
            ex.printStackTrace();
        }

        return false;
    }

    public IBPMContext getBPMContext() {

        try {
            if (bpmContext == null) {

                bpmContext = getIBPMContext(adminUsername, adminPassword);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bpmContext;
    }

    public static IBPMContext getIBPMContext(String username,
                                             String password) throws Exception {
        return getBPMServiceClientFactory().getBPMUserAuthenticationService().authenticate(username,
                                                                                           password.toCharArray(),
                                                                                           null);
    }

    public static BPMServiceClientFactory getBPMServiceClientFactory() {

        bpmURL = "t3://localhost:8001";
        adminUsername = "weblogic";
        adminPassword = "welcome1";

        Map properties = new HashMap();

        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                       WorkflowServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,
                       bpmURL);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        return BPMServiceClientFactory.getInstance(properties, null, null);
    }

}

       
 

Note that you have to add the Organization Service into the foreign JNDI on your domain:
Name: ejb/bpm/services/BPMOrganizationServiceBean
Local JNDI Name: ejb/bpm/services/BPMOrganizationServiceBean
Remote JNDI Name: ejb/bpm/services/BPMOrganizationServiceBean

 CustomWorklistUtils.java

Thursday, March 5, 2015

Solving GWT - JPA/Hibernate Problem

GWT + JPA/Hibernate Problem 

GWT is an open source framework that makes writing AJAX applications easy. Actually very easy but when you want to connect your Presentation layer (Written Using GWT) with your current Model layer (Hibernate/JPA annotated), here comes the agony.

The problem happens when you want to use your models in GWT client side, because GWT actually do compile all code in Client side to JAVASCRIPT and that require providing the source code for every java classes used in Client side.

That leaves us with several options to choose from:

A-Using DTO approach:
You can solve the problem by creating DTOs to all your models and using a mapping tool like DOZER.
But that solution is really painful, because you will have to generate DTO each time you make a small change in your Model layer.

B-Using Gilead (Hibernate for GWT).

C-Using OUR solution:
1-You will need to generate your model jar with the source code included .. it can easily achieved with maven, and also you will need to add the xxx.gwt.xml file to your model root path.
xxx.gwt.xml sample
<?xml version="1.0" encoding="UTF-8"?>
<module>
  <inherits name='com.google.gwt.user.User'/>
  <source path="model">
  </source>
</module>

For example if your models path as com.mycompany.myproject.model you will put the xml in myproject folder.

2-Now after we have a good generated model jar, now we want the GWT Compiler to understand and compile the models with hibernate annotations, this can be done easily by getting hibernate annotations jar with source code (You will find it easily by searching Google ) and add this jar to your web app class path, this will be enough to make the GWT compiler do it’s work without a problem.
Now Add your model jar to your GWT project class path and add the following entry to your gwt.xml file

<inherits name='<package-location>' />
Example: <inherits name='com.mycompany.myproject.model' />


3- Now our problem is almost solved:

How to handle hibernate entities (Persistent Set, …etc) because GWT cannot serialize this objects :

You can use Dozer for this small operation as it transform the Persistent set to its original Collection object.
How to handle lazy initialization:
Using Dozer and “CustomFieldMapper “ to replace lazy Objects with null values in the mapping operation.