Wednesday, 4 December 2013

Working with Workflow Email Action

1. Goto wcmconfigservices.properties file location and configure smtp server details, username, password etc.

2.

Tuesday, 3 December 2013

Working with Google Analytics Core Reporting API

Ref URL
   
https://code.google.com/p/google-api-java-client/source/browse/?repo=samples
https://developers.google.com/analytics/devguides/reporting/core/v3/

First

1. Configure Website with Google Analytics
2. Configure Google Cloud Console and Register Application
3. Used Google APIs Client Library for Java
4. Import required jar files and implemented Java Code in IDE(Netbeans)

Steps

1. Create a website configured with Google Analytics (http://www.google.com/analytics)
        - Get the .js snippet and copy that code in the pages that have to be tracked
       
2. Create a project and application in 'Google Cloud Console' (https://cloud.google.com/console)
        - Create a project, where project id is auto generated.
        - Inside project -> APIs & auth -> Registered apps, Register an application
        - Inside Registered Application -> OAuth 2.0 Client ID, you will get '.json file', 'Client Id' and 
           'Client Secret', which looks like;
            .json file - Click on Download JSON, which gives required credential file which is used in our code
                Client Id - 559413053225-u9ehiskrqlpc1mh253klsom4sujbn3.apps.googleusercontent.com
                Client Secret - kfwsd_GrOkhxQNt_MXfEoLvM
       
3. Code is mentioned below, by executing which provides Dimensions and Metrics.

Note - Download required jar files from Client Library

/** Working Code **/

package googleanalytics;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.AnalyticsScopes;
import com.google.api.services.analytics.model.Accounts;
import com.google.api.services.analytics.model.GaData;
import com.google.api.services.analytics.model.GaData.ColumnHeaders;
import com.google.api.services.analytics.model.Profiles;
import com.google.api.services.analytics.model.Webproperties;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.List;

public class HelloAnalyticsApiSample {

  /**
   * Be sure to specify the name of your application. If the application name is {@code null} or
   * blank, the application will log a warning.
   */
  private static final String APPLICATION_NAME = "blogapp";

  /** 'analytics_sample' is the Directory to store user credentials and 'user.home' is the path **/
  private static final java.io.File DATA_STORE_DIR =
      new java.io.File(System.getProperty("user.home"), "analytics_sample");
 
  /**
   * Globally shared instance across your application.
   */
  private static FileDataStoreFactory dataStoreFactory;

  /** Global instance of the HTTP transport. */
  private static HttpTransport httpTransport;

  /** Global instance of the JSON factory. */
  private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

  /**
   * Main demo. This first initializes an analytics service object. It then uses the Google
   * Analytics Management API to get the first profile ID for the authorized user. It then uses the
   * Core Reporting API to search terms. Finally the results are printed
   * to the screen. If an API error occurs, it is printed here.
   *
   */
  public static void main(String[] args) {
    try {     
      httpTransport = GoogleNetHttpTransport.newTrustedTransport();
      System.out.println("main call httpTransport :: "+httpTransport);
      dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
      System.out.println("main call dataStoreFactory :: "+dataStoreFactory);
      Analytics analytics = initializeAnalytics();     
      String profileId = getFirstProfileId(analytics);
      System.out.println("analytics details :: "+analytics);
      System.out.println("profileId is ::"+profileId);
      if (profileId == null) {
        System.err.println("No profiles found.");
      } else {
        GaData gaData = executeDataQuery(analytics, profileId);
        printGaData(gaData);
      }
    } catch (GoogleJsonResponseException e) {
      System.err.println("There was a service error: " + e.getDetails().getCode() + " : "
          + e.getDetails().getMessage());
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }
 
  /**
   * Performs all necessary setup steps for running requests against the API.
   *
   * @return An initialized Analytics service object.
   *
   * @throws Exception if an issue occurs with OAuth2Native authorize.
   */
  private static Analytics initializeAnalytics() throws Exception {
    // Authorization.
    System.out.println("inside initializeAnalytics method ");
    Credential credential = authorize();
    System.out.println("Credentials details :: "+ credential);

    // Set up and return Google Analytics API client.
    return new Analytics.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(
        APPLICATION_NAME).build();
  }

  /** Authorizes the installed application to access user's protected data. */
  private static Credential authorize() throws Exception {
    // load client secrets
    System.out.println("inside Credential authorize method");
    // client_secrets.json is the file which consists of client_id and client_secret which is used for access
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(
            HelloAnalyticsApiSample.class.getResourceAsStream("client_secrets.json")));   
    if (clientSecrets.getDetails().getClientId().startsWith("Enter")
        || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
      System.out.println(
          "Enter Client ID and Secret from https://code.google.com/apis/console/?api=analytics "
          + "into Google Analytics/Source Packages/google analytics/client_secrets.json");
      System.exit(1);
    }   
    // set up authorization code flow
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
        httpTransport, JSON_FACTORY, clientSecrets,
        Collections.singleton(AnalyticsScopes.ANALYTICS_READONLY)).setDataStoreFactory(
        dataStoreFactory).build();
    // authorize
    System.out.println("End Credential authorize method");
    return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");   
  }

   /**
   * Returns the first profile id by traversing the Google Analytics Management API. This makes 3
   * queries, first to the accounts collection, then to the web properties collection, and finally
   * to the profiles collection. In each request the first ID of the first entity is retrieved and
   * used in the query for the next collection in the hierarchy.
   *
   * @param analytics the analytics service object used to access the API.
   * @return the profile ID of the user's first account, web property, and profile.
   * @throws IOException if the API encounters an error.
   */
  private static String getFirstProfileId(Analytics analytics) throws IOException {
    String profileId = null;

    // Query accounts collection.
    Accounts accounts = analytics.management().accounts().list().execute();

    if (accounts.getItems().isEmpty()) {
      System.err.println("No accounts found");
    } else {
      String firstAccountId = accounts.getItems().get(0).getId();

      // Query webproperties collection.
      Webproperties webproperties =
          analytics.management().webproperties().list(firstAccountId).execute();

      if (webproperties.getItems().isEmpty()) {
        System.err.println("No Webproperties found");
      } else {
        String firstWebpropertyId = webproperties.getItems().get(0).getId();

        // Query profiles collection.
        Profiles profiles =
            analytics.management().profiles().list(firstAccountId, firstWebpropertyId).execute();

        if (profiles.getItems().isEmpty()) {
          System.err.println("No profiles found");
        } else {
          profileId = profiles.getItems().get(0).getId();
        }
      }
    }
    return profileId;
  }

  /**
   * Returns the top 25 organic search keywords and traffic source by visits. The Core Reporting API
   * is used to retrieve this data.
   *
   * @param analytics the analytics service object used to access the API.
   * @param profileId the profile ID from which to retrieve data.
   * @return the response from the API.
   * @throws IOException tf an API error occured.
   */
  private static GaData executeDataQuery(Analytics analytics, String profileId) throws IOException {
    System.out.println("inside executeDataQuery");
    return analytics.data().ga().get("ga:" + profileId, // Table Id. ga: + profile id.
        "2013-11-25", // Start date.
        "2013-11-25", // End date.
        "ga:visits,ga:newVisits,ga:avgPageLoadTime") // Metrics.
        .setDimensions("ga:pagePath,ga:pageTitle")
        .setSort("-ga:newVisits,ga:source")
        .setFilters("ga:medium==organic")
        .setMaxResults(25)
        .execute();
  }

  /**
   * Prints the output from the Core Reporting API. The profile name is printed along with each
   * column name and all the data in the rows.
   *
   * @param results data returned from the Core Reporting API.
   */
  private static void printGaData(GaData results) {
    System.out.println("printing results for profile: " + results.getProfileInfo().getProfileName());

    if (results.getRows() == null || results.getRows().isEmpty()) {
      System.out.println("No results Found.");
    } else {

      // Print column headers.
      for (ColumnHeaders header : results.getColumnHeaders()) {
        System.out.printf("%30s", header.getName());
      }
      System.out.println();

      // Print actual data.
      //System.out.println("Get Rows Name"+results.getRows());
      for (List<String> row : results.getRows()) {
        for (String column : row) {
          System.out.printf("%30s", column);
        }
        System.out.println();
      }

      System.out.println();
    }
  }
}

Monday, 1 July 2013

Implementation of Rating Widget in WebSphere portal 8

1. Create some content.
2. Create menu component and call created content.
3. In menu component result design, copy below code

[Element context="autofill" type="content" key="image"]<br/><br/>  // this may be any content element tag
        [Element context="autofill" type="content" key="Body"]<br/>  // this may be any content element tag


<div class="lotusui30" id="inlineWidgets_[Property context="autofill" type="content" format="uri" field="id"]">
  <div dojoType="com.ibm.widgets.InlineRating"
 resourceID="[Property context="autofill" type="content" format="uri" field="id"]"
 resourceTitle="[Element context="autofill" type="content" key="Title"]"
 ratingScope ="all" displayTwisty = "HIDDEN" showDialogLauncher = "false"
 onStarClickOpenDialog = "true” customLabel ="" >
  </div>
</div>

<script type="text/javascript">
  dojo.addOnLoad(function(){
dojo.forEach( ["inlineWidgets_[Property context="autofill" type="content" format="uri" field="id"]"], dojo.parser.parse, dojo.parser);
  });
</script>

Where:
[Property context="autofill" type="content" format="uri" field="id"]  ==  retrive specific content id like; wcm:oid:84c936b3-e8a1-4882-8a0a-9b509ad5231e

4. Create a Presentation Template and call created menu component.
5. Create a page, and add new parameters to the page.
6. To add parameters, goto Page->Page Properties->Advanced Options->click on "I want to set parameters".
7. And add following parameters,
New Parameter - resourceaggregation.profile
New Value     - profiles/profile_full.json

8. Configure page with Presentation template and sitearea.

Ref Url:

http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Rating_WCM_content_lpr_Detailed_example_provided_to_reference_rating_widget_from_a_WCM_menu_componentrpr



Friday, 28 June 2013

Websphere Portal Syndication and Subscribe Process

Syndication is the process to replicate data from a web content library of one server(XXX) to a web content library on another server(YYY).
The relationship between a syndicator and a subscriber can be either a one-way, two-way are Multiple syndication relationships.

Assume : Server(XXX) as Syndicator
                   Server(YYY) as Subscriber

Here we are getting data from Server(XXX) to Server(YYY)

You can syndicate only between servers running the same version. You cannot syndicate between different versions.

You can syndicate between versions 8.0.0.0 and 8.0.0.1.
You cannot syndicate between versions 7.0.0.0 and 8.0.0.0.

To establish relationship between two servers for syndication follow below steps,

Process :

1. Check both servers are running and can establish connection over network.
2. On subscriber machine(ServerYYY), create vault slot.
Goto, Websphere portal Administration->Access->Credential Vault->Add a vault slot
3. Fill the details like Name,Vaultresource and check "Vault slot is shared" and provide credentials of syndicator server
4. Click OK.
5. Now you have to create Subscriber, Goto Websphere portal Administration->Portal Content->Subscribers and click 'SubscribeNow' button
6. Provide the details like,
Syndicator URL: http://<HOST>:<PORT>/wps/wcm
Syndicator Name: Unique name anything
Subscriber Name: Unique name anything
Credential Vault Slot: select credential vault slot just you created
7. Click next and select libraries you want to syndicate and click finish.
8. Now you can see created subscriber.
9. Test connection of this subscriber with syndicator and update/rebuild the subscriber to establish syndication from one server to other.

Note :

To syndicate a library that contains more than 10000 items, update the maximum Java heap size used by the portal application server on the subscriber server:

In the WebSphere® Integrated Solutions Console, navigate to the Java virtual machine settings.
Stand-alone server:
Servers -> Server Types -> WebSphere application servers -> WebSphere_Portal -> Java and Process Management -> Process definition -> Java Virtual Machine

Clustered server:
System administration -> Deployment manager -> Java and Process Management -> Process Definition -> Java Virtual Machine

Update the value in the Maximum Heap Size field. A value of at least 1024 MB is recommended.
Click OK, and then save your changes.


Ref URL :

http://www-10.lotus.com/ldd/portalwiki.nsf/xpDocViewer.xsp?lookupName=IBM+Web+Content+Manager+8+Product+Documentation#action=openDocument&res_title=Administering_syndication_wcm8&content=pdcontent


Monday, 24 June 2013

Extending WebSphere Portal Personalization engine using Application Objects

To my understand,

This custom application object works based on user attributes which are accessable through PUMA.
We call this attributes, in java class user defined methods which return boolean.
Based on method return, pages/portlets shows or hide.

Sample Code
-----------
import java.io.Serializable;
import java.util.*;
import com.ibm.websphere.personalization.RequestContext;
import com.ibm.websphere.personalization.applicationObjects.*;

// class name will be used in application object
public class PersonalizationAppObject implements SelfInitializingApplicationObject, Serializable{

--variable declaration--

// for object intialization
public void init(RequestContext context){
--context--
--user--
--Attributes--
}
--setting session-- // to access environment

public boolean getCountry(){ // method name refers as an attribute
        if(--condition--){
            return true;
        }
        return false;
    }
}

Implementation
--------------
1. Get required jar files(pznauthor.jar, pzncommon.jar, pznquery.jar, pznresources.jar, psnruntime.jar) from "\pzn\prereq.pzn\lib" and add jar files to classpath.
2. Create a java class implementing "SelfInitializingApplicationObject".
3. Initialize this object using init() method.
4. Write a user defined method where we access environment using context path.
5. And based on user attribute this method return true/false.
6. Make a jar file of the generated java class file and copy that into "\pzn\prereq.pzn\collections".
7. Restart the portal server.
8. To add the application object to personalization engine.
9. Create new Application Object providing session attribute(same has specified in class) and class name.
10. Now create Visibility Rule for page/portlet.
11. Click on attribute link and select your Application Object.attribute (here attribute is method name specified in class)
12. If attribute returns true, page shows or else hide.

Ref Url : http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Extending_WebSphere_Portal_Personalization_engine_using_Application_Objects

Wednesday, 1 May 2013

How to show up Import-xml portlet for Virtual Portals in WebSphere.

To show up we have to grant permissions for virtual resources as mentioned below:

1. Goto, Administration->Access->Resource Permission->Virtual Resources->PORTAL
         click on Assign Access, select Edit Role of Security Administrator and assign required user there.
       
2. Goto, Administration->Access->Resource Permission->Virtual Resources->XML ACCESS
         click on Assign Access, select Edit Role of Editor and assign required user there.
       
       
Assigning this permissions shows import-xml for virtual portals.


Thanks,
Suman






How to delete IBM WebSphere Virtual Portal Context

To delete Virtual Portal Context path immediately, we have to run Task.xml file for Datastore Cleanup.

location of Task.xml file :  /opt/IBM/WebSphere/PortalServer/doc/xml-samples
where to run                     :   /opt/IBM/WebSphere/wp_profile/PortalServer/bin

What is Task.xml file ?

--> Task.xml file is a scheduler file which runs at specified schedule time(once/daily/weekly/monthly).

--> It performs Datastore cleanup task(com.ibm.portal.datastore.task.ResourceCleanup); i.e.

--> if we delete a virtual portal and want to create another virtual portal with same context path immediately.

--> we will get an exception

    "com.ibm.portal.WpsException: EJPEB0806E: Creating a virutal portal failed because a unique key constraint in the data backend was violated. Likely a virutal portal with the same context was deleted but still exists in the database. It is recommended to run the cleanup task for deleting resources by running the XML script Task.xml using the XML configuration interface."
   
    because cleanup task runs only at a specified time so context path will reside in database still.

 --> To overcome this exception we have to run cleanup task manually.

Process to Run Task.xml file

1. Goto '/opt/IBM/WebSphere/wp_profile/PortalServer/bin' location and execute below command

    ./xmlaccess.sh -in /opt/IBM/WebSphere/PortalServer/doc/xml-samples/Task.xml -user username -password pwd -url http://(IP Address):(port)/wps/config -out taskresult.xml
   
2. After successfully running of the command, you can create new virtual portal with same context path.


Thanks,
MS

Monday, 22 April 2013

Implementing Impersonate Feature

Impersonate is an WCM feature, by which one user can preview other user content and modify it without knowing his login credentials.

Process for implementing impersonate feature:

1. Goto User and Group Permissions.
2. Search for the user, whom you want to give "impersonate" feature enable.
3. Select "Select Resource Type" of that user.
4. Select "Virtual Resources" link.
5. Goto "USERS" and click on "AssignAccess".
6. And Explicitly Assigned "Can Run As User" permission.

Ref url : http://www-10.lotus.com/ldd/portalwiki.nsf/dx/User_Impersonation_in_Websphere_Portal_Server



Publish a Project and all contents in the Project


***
We can publish a Project and all contents in project if and only if they(content) are in 'Pending' status.
***

1. Create a Workflow for content items, With two stages.
-> Create workflow action (Publish)
-> Create two workflow stages
-> In first WorkflowStage,
Run on Entering Stage : None
Run on Exiting Stage : None
   Joint approval: check
Enter comment on approval: check
Approver: required user
-> In second WorkflowStage,
Run on Entering Stage: Assign the publish action you created
Run on Exiting Stage: None
   Joint approval: check
Enter comment on approval: check
Approver: required user
-> Create Workflow
-> Workflow Stages:
first workflowstage
second workflowstage
-> Reject Stage: None

2. Create a content item based on above created workflow and save. Content will be in "Draft" status.

3. Create a New Project,
        -> Publish Option : Manual
-> Approval  : Add user who will approve the project
-> Require approval from : depends on your requirement
-> Require a comment from the approver : Check
-> Save and close, now created project will be in "Active" state.

4. Now add contents(draft status) to project.
5. In project, To move content into next status, check the content and click on 'More' dropdown and select 'Approve'.
6. Content move to the next state 'Publish Pending'.
7. Now we have to submit project for 'Review' by clicking 'Submit for Review' button.
8. Project change to 'Review' state.
9. Now we have to approve project by clicking 'Approve Project' button.
10. Here project change to 'Pending' state.
11. Now we can publish project by clicking 'Publish Project' button.
12. Here project state change to 'Published' and content state also changes to 'Published'.

Through JSP we can publish the project by running below code


<%@ page import="com.ibm.workplace.wcm.api.*"%>
<%@ page import="com.ibm.workplace.wcm.api.exceptions.*"%>
<%@ page import="java.util.*,javax.servlet.jsp.JspWriter,java.io.*,java.util.Iterator"%>

<%

try{
// Workspace
Workspace myworkspace = WCM_API.getRepository().getSystemWorkspace();
myworkspace.login();
myworkspace.setCurrentDocumentLibrary(myworkspace.getDocumentLibrary("LibraryName"));

DocumentId docid = null;
DocumentIdIterator docid_iterator = null;
String projectName = null;
Project userProject = null;

// Specifing our project
docid_iterator = myworkspace.findByName(DocumentTypes.Project, "ProjectName");

if(docid_iterator.hasNext()){
docid = docid_iterator.nextId();
userProject = (Project)myworkspace.getById(docid);
// To get project name
projectName = userProject.getName();
// To get item count in project
long val = userProject.getItemCount();
//out.println("Poject Name is :: "+projectName+"<br>Number of Items in Project :: "+val);
// to get items/content of specified project
Iterator ie = userProject.getItems();
while(ie.hasNext()) {
Content con_obj = (Content)ie.next();
//out.println("<br>Content Object :: "+con_obj);
// To get approver names for content item
String approvers[] = con_obj.getCurrentApprovers();
for(int i=0; i<approvers.length; i++){
//out.println("<br>Content Approvers are :: "+approvers[i]);
}
// Move content to nextworkflowstage
con_obj.nextWorkflowStage();
}
}

// To get approver names for Project
String projectapprover[] = userProject.getCurrentApprovers();
for(int i=0; i<projectapprover.length; i++){
//out.println("<br>Project Approvers are :: "+projectapprover[i]);
}

// To publish a project when all items in project are move to next state
userProject.publish();

}
catch(Exception e){
e.printStackTrace();
}

%>