Monday, May 11, 2015

Webcenter portal/ADF Skin Resource Bundle

The text used in a skin like 'Detach' button in a panel collection is defined in a resource bundle. you can override the text by creating a custom resource bundle and declaring only the text you want to change. After you create your custom resource bundle, register it with the skin.

Sample of a skin resource bundle

       

af_panelCollection.LABEL_DETACH_TABLE_DLG = Detach

af_panelCollection.LABEL_MENUITEM_DETACH = Detach

af_panelCollection.TIP_BUTTON_DETACH = Detach

af_dialog.LABEL_OK=Ok

af_dialog.LABEL_CANCEL=cancel

af_query.LABEL_RESET=Reset

af_query.LABEL_OK=Ok

In ADF:

To Register the skin resource bundle, edit trinidad-skins.xml in your ADF Application and add the <bundle-name> tag with the Resource bundle path:

       

<?xml version="1.0" encoding="windows-1252" ?>

<skins xmlns="http://myfaces.apache.org/trinidad/skin">

  <skin>

    <id>myskin.desktop</id>

    <family>myskin</family>

    <extends>skyros-v1.desktop</extends>

    <style-sheet-name>css/layout.css</style-sheet-name>

    <bundle-name>com/mycompany/myproject/view/bundle.myBundle</bundle-name>

  </skin>

</skins>

       
 

Don't forget to use your custom skin by editing trinidad-config.xml:

       

<?xml version="1.0" encoding="windows-1252"?>

<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">

  <skin-family>myskin</skin-family>

</trinidad-config>

       
 

In Webcenter Portal (Using Spaces (Portal Builder)):

Go to the \Middleware\Oracle_WC1\webcenter\modules\oracle.portlet.server_11.1.1 and edit oracle.webcenter.skin.ear\APP-INF\lib\spaces-web-skin.jar\META-INF\trinidad-skins.xml

Find the main skin you are already extending in Spaces and add the <bundle-name> with your bundle path.
but make sure that the bundle is already exist in a shared library that Webcenter portal is already referring to.
And also keep in mind that this change will affect the whole portal application, so if you removed the shared library that contain the Resource bundle, the whole portal application will fail to start.

       
  <!-- Fusion skins -->

  <skin>

    <id>webcenter-fusion-internal.desktop</id>

    <family>webcenter-fusion-internal</family>

    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>

    <style-sheet-name>adf/spaces/skins/webcenter-fusion-internal/webcenter-fusion-internal.css</style-sheet-name>

    <extends>fusionFx-v1.3.desktop</extends>

     <bundle-name>com/mycompany/myproject/view/bundle.myBundle</bundle-name>

  </skin>

       
 

Restart Spaces.




Multilingual Portal Implementation with Webcenter Portal 11.1.1.8

In this article 'Namit Kakkar' walks you through one use case on how to implement a multilingual Portal.

Full Article

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.

Tuesday, February 3, 2015

Integrate ADF Taskflows with Oracle Webcenter Portal:Spaces(Builder)

One of the most important features of Oracle Webcenter Portal:Spaces is the integration with ADF Taskflows, in this post I'll explain how to achieve that step by step.

1. We need to deploy our ADF application which contain all the taskflows as an ADF Shared Library




1.1 Go to Project Properties > Deployment


1.2 Press the new button and choose "ADF Library JAR File" as Archive Type and confirm.


1.3 Now Right Click your view controller and go to Deploy > (Your Deployment profile name)



1.4 Press Next > Finnish



1.5 After Successful deployment of the JAR file, get it from your view controller Deploy Folder.

2. Now we need to create a Wrapper web application to contain the ADF Shared library in order to deploy it in weblogic as a Shared Library.



2.1 Type your shared library name, this name with be used from Webcenter portal for reference.



2.2 Continue with creation wizard as we don't need any thing from this web application except containing our ADF Shared JAR.

2.3 Deploy your project to WAR and get the WAR from your deploy folder.



2.4 Delete any entries in web.xml and weblogic.xml

2.5 create a lib folder inside WAR > WEB-INF and add the ADF shared library in it.

2.6 Open Weblogic Administration Console



2.7 Go to Deployments > Install > Upload your file and choose your WAR (Shared Library)



2.8 Make sure that you choose "Install this deployment as a library"



2.9 Make sure that the Shared Library targets WC_Spaces and Finnish





Now we have a shared library deployed on our application server, but we still need to use the task flows inside this shared library.

To achieve this we need to refer to this shared library from portal by using the extend.spaces.webapp web application.

3. Go back to JDeveloper and create a new Webcenter Portal Server Extension

Note: you need to install the Webcenter extensions to your JDeveloper by going to 
Help > Check for updates  and search for portal extensions and download it.



3.1 Continue your creation wizard normally.



3.2 You will find two projects in the created application: PortalExtention and PortalSharedLibrary

3.3 Right click on PortalSharedLibrary > New > "Search for weblogic in all applications" > Choose Weblogic Deployment Descriptor > weblogic.xml > Finnish

3.4 Edit weblogic.xml and add your Shared Library reference (Your WAR Name)



 3.5 Go to your PortalSharedLibrary project and edit MANIFEST.MF and increase the "Implementation-Version" number.



3.6 Deploy PortalSharedLibrary



3.7 Choose your domain connection and check the  "Deploy to selected instances in the domain" and choose WC_SPACES AND also check the "Deploy as a shared Library" and Finnish




After successful deployment, now Oracle Webcenter Portal:Spaces can use the shared task flows from your ADF application.

4 Add the shared taskflows to your Portal.

4.1 Go to http://<host>:<port>/webcenter/portal/builder URL in your portal and login.

4.2 Go to Shared Assets(1.8) or Resources(in earlier versions) tab.

4.3 Select Resource Catalogs and create a new one.



4.4 Check the Available check box in order to use this resource catalog in your portal pages.



     In earlier versions :

4.5 Edit the created resource catalog and press Add from Library



4.6 Now search for your taskflow name and add it.

That's it :) now you can use any of the registered taskflows in you Portal Pages.