WebSphere Portal – Error 404: EJCBD0006E: The resolution of a URI failed. Refer to the SystemOut.log for more detailed information.

If you encounter “Error 404: EJCBD0006E: The resolution of a URI failed. Refer to the SystemOut.log for more detailed information.” while clicking on Authoring UI portlet links (for example Select Workflow link as shown in the screenshot above) and your SystemOut.log is returning you:

[7/30/15 15:11:47:539 SGT] 00000124 ExceptionLogg W com.ibm.wps.logging.ExceptionLogger logThrowable An exception occurred: [EJCBC0009E: The entity [[ObjectIDImpl 'Z6_00000000000000A0BR2B300G10', CONTENT_NODE, VP: 16576, [Domain: rel], DB: C040-000000000000000080026B8B35008001]] could not be be found.]. Enable traces for [com.ibm.wps.logging.ExceptionLogger=all] to see the exception stack trace.
[7/30/15 15:11:47:543 SGT] 00000124 ResolvedPrepr I com.ibm.wps.resolver.portal.ResolvedPreprocessor process The resolution process failed, for more details enable tracing for [com.ibm.wps.resolver.portal.ResolvedPreprocessor=all].

 

This can be a issue with the “Web Content Authoring” page under Hidden Pages (Content Root > Hidden Pages > Web Content Authoring).

  1. Go to Administration > Portal User Interface > Manage Pages.
  2. Ensure that “Web Content Authoring” page is Active.
  3. Ensure that the particular user has a USER role for that page.

 

Notes on Regular Expression

  1. What is the difference between “*” and “+”?
    “*” will match the character zero or more times whereas “+” will match one or more times. For example, “\d*” regular expression will return the following results for:

    • 2b – will match “2b”
    • 3ab – will match “b” (since digit character is optional)

    Now consider “\d+” regular expression:

    • 2b – will still match “2b”
    • 3ab – will not return any match as “+” required one or more times matches.
  2. <continue…>

Javascript: How to Calculate Number of Working Days?

Date.workingDaysFrom(fromDate) calculates the number of working days between 2 Date objects (excluding weekends; Sat and Sun). The method will return “-1” if the fromDate is an invalid Date object or is later than the compared Date.

Do take note that this method does not take public holidays into consideration and each date is consider as a full day.

Date.prototype.workingDaysFrom=function(fromDate){
 // ensure that the argument is a valid and past date
 if(!fromDate||isNaN(fromDate)||this<fromDate){return -1;}

 // clone date to avoid messing up original date and time
 var frD=new Date(fromDate.getTime()),
     toD=new Date(this.getTime()),
     numOfWorkingDays=1;

 // reset time portion
 frD.setHours(0,0,0,0);
 toD.setHours(0,0,0,0);

 while(frD<toD){
  frD.setDate(frD.getDate()+1);
  var day=frD.getDay();
  if(day!=0&&day!=6){numOfWorkingDays++;}
 }
 return numOfWorkingDays;
};

 

Examples

Comparing 8-Jul-2015 (Wed) to 13-Jul-2015 (Mon)

var startDate = new Date("8/8/2015");
var endDate = new Date("13/8/2015");
endDate.workingDaysFrom(startDate); // returns 4

Comparing same date, 8-Jul-2015 (Wed)

var startDate = new Date("8/8/2015");
var endDate = new Date("8/8/2015");
endDate.workingDaysFrom(startDate); // returns 1

 

How to Generate Facebook Access Token for Public Page Feed?

Most clients would prefer a customized Facebook feed (especially those supporting multiple social media) , hence this bring us to this question:

“What is the easiest method to generate a Facebook access token just to retrieve their public page feed?”

A simple step is to create an “empty” Facebook application and use its access token (note that most likely the UI is going to change but the idea is there):

  1. Go to https://developers.facebook.com/apps/
  2. Go to “Add a New App” (My Apps > Add a New App).
  3. Select “WWW” (or any) and click on “Skip and Create App ID”.
  4. Give the application a suitable name and namespace for future reference.
  5. Grats! You have generated your own access token! For secret key, remember to click on the “Show” button.
  6. To verify, key in the following url and you should be able to see the public page feed:
    https://graph.facebook.com/v2.3/<page id>/posts?access_token=<App ID – as shown in above image>|<App Secert>

WebSphere: How to Access Portal Theme Tags in JSP?

Add “<%@ taglib uri=”/WEB-INF/tld/portal.tld” prefix=”portal” %>” in order to access the portal theme tags like “<portal-logic/>” and “<portal-navigation/>“.

To call the tag function, simply call <portal:<function name>/>. For example in portal theme, we would call:


<portal-logic:if loggedIn="yes">...</portal-logic:if>

to


<portal:if loggedIn="yes">...</portal:if>

WebSphere Portal is Throwing “Could not load ‘dojo.nls.dojo_en'” error

We have logged a PMR with IBM recently about the browser is complaining that it could not load ‘dojo.nls.dojo_en’.

could not load dojo.nls.dojo_en

And IBM official response is to apply Deferred with Dojo (“profiles/profile_deferred.json”) theme profile directly to the page and this resolves the issue for me.

How to apply “Deferred with Dojo” profile:

  1. At the front-end, turn on the “Edit Mode“.
  2. Click on Menu (below Edit Mode) > Edit Page Properties.
  3. Click on the Advanced tab and select “Deferred with Dojo” Profile.
  4. Click on the “Save” button.

 

Note: A simple method (which I like) is to add in “resourceaggregation.profile” page property and set “profiles/profile_dojo_deferred.json” as its value.

 

How to Create WebSphere Portal Custom Workflow Action?

IBM allows us to customize our own workflow action. It will comes in handy when you need the system to:

  • Insert/remove a reference database record whenever a content get published/expired
  • Send email notification to news subscribers whenever a news content get published
  • Customize the default WCM email notification message

Disclaimer: This article follows the steps listed in Creating a custom workflow action class and we have replaced WebContentCustomWorkflowService with WcmCustomWorkflowService. At this point, we can’t confirm if WcmCustomWorkflowService is the correct class replacement.

Steps to create your custom workflow action:

  1. Open your Eclipse or IBM® Rational® Application Developer and make sure Java EE developer tools add-on is installed.
  2. Click on File > New > Web Project.
  3. Key in your custom workflow project’s name. Select “Simple” as Project Templates and “Java EE” as Programming Model.
  4. Under Deployment tab, select “2.4” as Web module version and checked “Add project to an EAR“.
    Click on the “Finish” button.
  5. Create a java class that implements the interface com.ibm.workplace.wcm.api.custom.CustomWorkflowAction. This class is responsible for executing your codes.
    Note: In this example, we will only be doing System.out.println to prove that the custom workflow action works

    package xxx.xxx.xxx.cwf;
    
    import java.util.Date;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import com.ibm.workplace.wcm.api.Document;
    import com.ibm.workplace.wcm.api.WcmCustomWorkflowService;
    import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
    import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionResult;
    import com.ibm.workplace.wcm.api.custom.Directive;
    import com.ibm.workplace.wcm.api.custom.Directives;
    
    public class NewsAlertSubscriptionAction implements CustomWorkflowAction {
    
     @Override
     public CustomWorkflowActionResult execute(Document doc) {
      // Put your customized trigger codes here
      System.out.println("Executing NewsAlertSubscriptionAction");
      String msg = "";
      InitialContext initCtx = null;
      WcmCustomWorkflowService customWorkflowService = null;
      CustomWorkflowActionResult result = null;
    
      try {
       initCtx = new InitialContext();
       customWorkflowService = (WcmCustomWorkflowService) initCtx.lookup(WcmCustomWorkflowService.JNDI_NAME);
      } catch (Exception e) {
        msg = " - System has encountered exception (do check logs).";
        e.printStackTrace();
      }
    
      // directive: indicate if the content should proceed to the next stage
      // Check out WCM Javadoc for more valid directives information
      Directive directive = Directives.CONTINUE;
      System.out.println(" - document:" + doc.getName());
      return customWorkflowService.createResult(directive, msg);
     }
    
     @Override
     public Date getExecuteDate(Document arg0) {
      return DATE_EXECUTE_NOW;
     }
    }
    
  6. Create a custom workflow action factory class that implements the interface com.ibm.workplace.wcm.api.custom.CustomWorkflowActionFactory. This is the controller class, it is use to call the respective custom workflow actions.
    package xxx.xxx.xxx.cwf;
    
    import java.util.Locale;
    import com.ibm.workplace.wcm.api.Document;
    import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
    import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionFactory;
    
    public class XXXCustomWorkflowActionFactory implements CustomWorkflowActionFactory {
     String NEWS_ALERT_SUBSCRIPTION = "News Alert Subscription";
    
     @Override
     public CustomWorkflowAction getAction(String arg0, Document arg1) {
      if (arg0.equals(NEWS_ALERT_SUBSCRIPTION)) {
       return new NewsAlertSubscriptionAction();
      }
      return null;
     }
    
     @Override
     public String getActionDescription(Locale arg0, String arg1) {
      if (arg0.equals(NEWS_ALERT_SUBSCRIPTION)) {
       return "Send Email Alert to Subscribers";
      }
      return null;
     }
    
     @Override
     public String[] getActionNames() {
      String names[] = { NEWS_ALERT_SUBSCRIPTION };
      return names;
     }
    
     @Override
     public String getActionTitle(Locale arg0, String arg1) {
      return arg1;
     }
    
     @Override
     public String getName() {
      return "XXX Custom Workflow Actions";
     }
    
     @Override
     public String getTitle(Locale arg0) {
      return "XXX Custom Workflow Actions";
     }
    }
    
    
  7. Create a plugin.xml file if you are deploying using WAR or EAR. Include the plugin.xml file in the application’s “WEB-INF” folder.
    <?xml version="1.0" encoding="UTF-8"?>
    <plugin id="XXXCustomWorkflowActionsPlugin" name="XXX Custom Workflow Actions Plugin" version="1.0.0" provider-name="IBM">
    <extension point="com.ibm.workplace.wcm.api.CustomWorkflowActionFactory" id="XXXCustomWorkflowActionFactory">
    <provider class="xxx.xxx.xxx.cwf.XXXCustomWorkflowActionFactory"/>
    </extension>
    </plugin>
    
  8. Follow the Deploying custom plug-in applications to deploy your plugin.
  9. Go to Web Content Authoring portlet and create Custom Workflow Action, you should be able to select your custom workflow action as shown below.

 

WebSphere Portal 8.5: Customize Ephox Editor

Updates (6-Jul-2015): 
With Chrome (version 42) finally dropping support for NPAPI, we can only hope that Ephox Textbox.io can catch up with its predecessor - http://docs.ephox.com/display/IBMWCMTB/Textbox.io+for+IBM+WCM+Home.

We have been encouraging our clients to use Ephox Editor as their default WCM rich text editor ever since IBM has acquired Ephox Editor OEM licence. Hence it is important for us to know how to:

  • Customize Ephox Editor default menu and toolbar items (for example change the default font size from “pt” to “px”)
  • Apply our custom theme css classes styles in Ephox Editor

Most of the customization will be taking place at the config file, it is located at  <wp_profile>/installedApps/<cell>/wcm.ear/editor-editlive-config.war/config/config.xml.jsp.

 

Steps to customize Ephox Editor default editor settings:

  1. Read Setting Menu and Toolbar Items tutorial guide first.
  2. Edit the config file accordingly.
  3. Restart the server.

 

Steps to include custom theme css in Ephox Editor:

  1. Read Using CSS in the Applet tutorial guide first.
  2. Edit the config file accordingly.
  3. Restart server.