• ALL
  • CATEGORIES

Working with Publish Events in WebCenter Sites – Part 2

This is the second part of our introduction to PublishEventListeners in WebCenter Sites. The first part was published in December so if you need to refresh your memory take a look here.

This time we’re going to something a bit more useful with our event listener. We’re going to have a look at how we get a list of the assets published for each publish session and write them into a file. This could be useful from an audit or archive perspective as once we’ve got a handle on the asset in code we can do all sorts of things with it.

We can start by utilising the project we created for part one. Next we need to add a few new dependencies to our POM.

These two are WCS supplied jars:

<dependency>
    <groupId>com.fatwire.cs</groupId>
    <artifactId>assetapi</artifactId>
    <version>11.1.1.8.0</version>   
</dependency>   

<dependency>
    <groupId>com.fatwire.cs</groupId>
    <artifactId>cs</artifactId>
    <version>11.1.1.8.0</version>   
</dependency>

<dependency>
  <groupId>com.fatwire.gst</groupId>
  <artifactId>gst-foundation-all</artifactId>
  <version>11.6.1</version>
</dependency>

So we can install them to our local respository in the same way as before:

mvn install:install-file -Dfile=cs.jar -DgroupId=com.fatwire.cs -DartifactId=cs -Dversion=11.1.1.8.0 -Dpackaging=jar -DgeneratePom=true
mvn install:install-file -Dfile=assetapi.jar -DgroupId=com.fatwire.cs -DartifactId=assetapi -Dversion=11.1.1.8.0 -Dpackaging=jar -DgeneratePom=true

The third is the GST foundation project. This dependency isn’t strictly necessary but it does make working with WCS a bunch easier.

The download can be found here.

We’ll talk more about the GSF in another post. For now just install it to your maven repository as with the others:

mvn install:install-file -Dfile=gst-foundation-all-11.6.1.jar -DgroupId=com.fatwire.gst -DartifactId=gst-foundation-all -Dversion=11.6.1 -Dpackaging=jar -DgeneratePom=true

We now have two main tasks to complete.

  • The first is to amend our PublishEventListener so that instead of just logging information about the publish events it does something with particular events. In our case we want to listen out for events related to the publish session (SESSION) and only act once it has completed (DONE).
  • The second task involves getting a list of the assets published in the current session and noting them in a file.

To start we create a method that looks like this:

private boolean isPublishSessionComplete(PublishingEvent event) {
    return event.getTaskName().equals(SESSION) && event.getStatus().equals(DONE);
}

This method will return true when the event captured is related to the publish session (SESSION) and when that task has been completed.

Next we have a couple of methods to help us write our log file. For convenience we’re reusing the filesystem location that CSDT uses to output it’s exports.

private File getPublishSessionLogFile(PublishingEvent event, ICS ics) {
    String exportLocation = ics.GetProperty("cs.csdtfolder") + "/publish";
    makeSureFolderExists(exportLocation);
    File file = new File(String.format("%s/pub-session-%s.txt",exportLocation, event.getPubSessionId()));
    return file;
}

private void makeSureFolderExists(String exportLocation) {
    File dir = new File(exportLocation);
    if (!dir.exists()) {
        dir.mkdirs();
    }
}

and then a method to help us write out a file containing a list of asset published messages.

private void writePublishedAssetsToFile(PublishSession pubSession, File file) throws IOException {
    PrintWriter publishedAssetsWriter = new PrintWriter(new FileWriter(file));
    for (AssetId assetId : pubSession.getPublishedAssets()) {
        publishedAssetsWriter.println(String.format("Published asset: %s", assetId.toString()));
    }
    publishedAssetsWriter.close();
}

This method includes a new class that we need to write called PublishSession.

This class is a wrapper around two main database tables in WCS – PubSession and PubMessage. PubSession contains a row for each publish session and PubMessage records each of the messages that your see in you publish log. We can parse the data in PubMessage to identify the assets that have been published and log them to a file.

The meat of this class is the following SQL query:

SELECT ps.id as session_id, pm.cs_text as message FROM PubSession ps, PubMessage pm WHERE ps.id=pm.cs_sessionid AND ps.id= ? AND pm.cs_type='RESOURCE'

It returns all the rows in PubMessage where the type is RESOURCE (this helps us to exclude general messages).

We then look to filter out any messages that refer to tables being saved and to filter in any messages where the string contains  ‘:’

This isn’t perfect by any means but gives you a starting point for working with PubMessage.

if (!message.startsWith("TABLE") && message.contains(":")) {
    AssetId candidate = AssetIdUtils.fromString(message);
    publishedAssets.add(candidate);
}

So altogether our listener now looks like this:

package uk.co.manifesto.wcs.publishevents;

import static com.fatwire.realtime.event.PublishingStatusEnum.DONE;
import static com.fatwire.realtime.util.RealTimeConstants.PublishingTasks.SESSION;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import uk.co.manifesto.wcs.publishevents.session.PublishSession;
import COM.FutureTense.Interfaces.ICS;

import com.fatwire.assetapi.data.AssetId;
import com.fatwire.cs.core.event.EventException;
import com.fatwire.gst.foundation.facade.ics.ICSFactory;
import com.fatwire.realtime.event.PublishingEvent;
import com.fatwire.realtime.event.PublishingEventListener;

public class PublishListener implements PublishingEventListener {

    private static final Log log = LogFactory.getLog(PublishListener.class);

    public void onEvent( PublishingEvent event ) throws EventException {
        if (isPublishSessionComplete(event)) {
            ICS ics = ICSFactory.getOrCreateICS();
            PublishSession pubSession = new PublishSession(event.getPubSessionId(), ics);
            log.info(String.format("Logging data for publish session %s", event.getPubSessionId()));
            File file = getPublishSessionLogFile(event, ics);
            log.info(String.format("Creating log file  %s", file.getAbsolutePath()));

            try {
                writePublishedAssetsToFile(pubSession, file);
            } catch (IOException e) {
                log.error(e.getLocalizedMessage());
            }
        }
    }

    private File getPublishSessionLogFile(PublishingEvent event, ICS ics) {
        String exportLocation = ics.GetProperty("cs.csdtfolder") + "/publish";
        makeSureFolderExists(exportLocation);
        File file = new File(String.format("%s/pub-session-%s.txt",exportLocation, event.getPubSessionId()));
        return file;
    }

    private void makeSureFolderExists(String exportLocation) {
        File dir = new File(exportLocation);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    private void writePublishedAssetsToFile(PublishSession pubSession, File file) throws IOException {
        PrintWriter publishedAssetsWriter = new PrintWriter(new FileWriter(file));
        for (AssetId assetId : pubSession.getPublishedAssets()) {
            publishedAssetsWriter.println(String.format("Published asset: %s", assetId.toString()));
        }
        publishedAssetsWriter.close();
    }

    private boolean isPublishSessionComplete(PublishingEvent event) {
        return event.getTaskName().equals(SESSION) && event.getStatus().equals(DONE);
    }
}

And our PubSession class looks like this:

package uk.co.manifesto.wcs.publishevents.session;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import COM.FutureTense.Interfaces.ICS;
import COM.FutureTense.Interfaces.IList;
import COM.FutureTense.Util.IterableIListWrapper;

import com.fatwire.assetapi.data.AssetId;
import com.fatwire.cs.core.db.PreparedStmt;
import com.fatwire.cs.core.db.StatementParam;
import com.fatwire.gst.foundation.facade.assetapi.AssetIdUtils;

public class PublishSession {

    private ICS ics;
    private String pubSessionId;
    private String pubSessionSql = "SELECT ps.id as session_id, pm.cs_text as message, ps.cs_sessiondate as session_startdate, ps.cs_enddate as session_enddate FROM PubSession ps, PubMessage pm WHERE ps.id=pm.cs_sessionid AND ps.id= ? AND pm.cs_type='RESOURCE'";

    public PublishSession(String pubSessionId, ICS ics) {
        this.ics = ics;
        this.pubSessionId = pubSessionId;

    }

    public List<AssetId> getPublishedAssets() {
        List<AssetId> publishedAssets = new ArrayList<AssetId>();

        PreparedStmt publishMessages = new PreparedStmt( pubSessionSql,Arrays.asList(new String[]{"PubMessage" , "PubSession"}));
        publishMessages.setElement(0, "PubSession", "id");
        StatementParam pubSessionIdParam = publishMessages.newParam();
        pubSessionIdParam.setString(0, pubSessionId);

        for (IList row : new IterableIListWrapper(ics.SQL(publishMessages, pubSessionIdParam, true))) {
             try {
                String message = row.getValue("message");
                if (!message.startsWith("TABLE") && message.contains(":")) {
                    AssetId candidate = AssetIdUtils.fromString(message);
                    publishedAssets.add(candidate);
                }   
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }       
        return publishedAssets;
    }

}

Assuming that you’ve followed the instructions from part one about registering the listener we can now build and deploy our jar and run another publish.

Leave a reply

You can use these tags:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Sign up for the Manifesto newsletter and exclusive event invites