Extending Content Delivery Storage in SDL Tridion 2011 part 2

The Code

Tutorial Guide:

Part 1: The Concepts
Part 2: The Code
Part 3: Configuration and Testing

Java Entity Bean

We are writing our Entity Bean in a class called PublishAction.java. This is a Java Bean that defines the Java fields and their types corresponding to each column in the PUBLISH_ACTIONS table. Additionally, this class uses JPA (Java Persistency API) annotations to specify a mapping between the fields and columns, their auto generation policy (in case of the "id" primary key field) and even the correspondence of the DB table name.

Note: The little quirk here is that class PublishAction.java has to be in package com.tridion.storage (or in a sub-package of it):

package com.tridion.storage.extension.search;

 

Our bean has to extend class com.tridion.storage.BaseEntity and define using annotations that it maps to table PUBLISH_ACTIONS:

@Entity

@Table(name = "PUBLISH_ACTIONS")

public class PublishAction extends BaseEntity {

 

Define the class fields and map them to their DB table column counterpart:

@Column(name = "ACTION")

private String action = null;

 

Take special care of the class/table Primary Key. In our case ID:

@Id

@Column(name = "ID")

@SequenceGenerator(name = "SEQ_PUBLISH_ACTIONS", sequenceName = "SEQ_PUBLISH_ACTIONS")

@GeneratedValue(generator = "SEQ_PUBLISH_ACTIONS")

private long id;

 

Note: This is where we specify the Sequence we defined earlier (in case our DB is Oracle). For SQLServer, you can still leave this annotation in - it will be ignored.

Define all Getters and Setters for the Bean properties:

public String getAction() {

       return action;

}

 

public void setAction(String action) {

       this.action = action;

}

 

Finally, putting it all together, gives us the whole Bean Entity class:

package com.tridion.storage.extension.search;

 

import java.util.Date;

 

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.SequenceGenerator;

import javax.persistence.Table;

 

import com.tridion.storage.BaseEntity;

 

/**

 * @author Mihai Cadariu

 */

@Entity

@Table(name = "PUBLISH_ACTIONS")

public class PublishAction extends BaseEntity {

 

       privatestatic final longserialVersionUID = 8991018647646020749L;

 

       @Id

       @Column(name = "ID")

       @SequenceGenerator(name = "SEQ_PUBLISH_ACTIONS", sequenceName = "SEQ_PUBLISH_ACTIONS")

       @GeneratedValue(generator = "SEQ_PUBLISH_ACTIONS")

       privatelong id;

 

       @Column(name = "ACTION")

       private String action = null;

 

       @Column(name = "URL")

       private String url = null;

 

       @Column(name = "TCMURI")

       private String tcmUri = null;

 

       @Column(name = "CREATION_DATE")

       private Date creationDate = null;

 

       @Column(name = "CONTENT")

       private String content = null;

 

       public String getUrl() {

              return url;

       }

 

       publicvoid setUrl(String url) {

              this.url = url;

       }

 

       publiclong getId() {

              return id;

       }

 

       publicvoid setId(long id) {

              this.id = id;

       }

 

       public Date getCreationDate() {

              return creationDate;

       }

 

       publicvoid setCreationDate(Date creationDate) {

              this.creationDate = creationDate;

       }

 

       public String getContent() {

              return content;

       }

 

       publicvoid setContent(String content) {

              this.content = content;

       }

 

       public String getAction() {

              return action;

       }

 

       publicvoid setAction(String action) {

              this.action = action;

       }

 

       publicint getObjectSize() {

              return 80;

       }

 

       public Object getPK() {

              return Long.valueOf(id);

       }

 

       public String getTcmUri() {

              return tcmUri;

       }

 

       publicvoid setTcmUri(String tcmUri) {

              this.tcmUri = tcmUri;

       }

 

       public String toString() {

              return String.format("[PublishAction:id=%s,action=%s,url=%s,tcmuri=%s,creationDate=%s,content=%s]", id, action,

                     url, tcmUri, creationDate, content);

       }

}

DAO (Data Access Object) Interface

This interface defines the operations that we can perform on the Entity Bean. In our case, we want to simply allow the CRUD methods, therefore we only define store, findByPrimaryKey, update and remove.

The following code is the actual interface defined for the PublishActions DAO:

package com.tridion.storage.extension.search;

 

import com.tridion.broker.StorageException;

 

/**

 * @author Mihai Cadariu

 */

publicinterface PublishActionDAO {

       publicabstract PublishAction store(PublishAction publishAction) throws StorageException;

 

       publicabstract PublishAction findByPrimaryKey(long l) throws StorageException;

 

       publicabstract PublishAction update(PublishAction publishAction) throws StorageException;

 

       publicabstractvoid remove(long l) throws StorageException;

}

JPA DAO Implementation Class

The purpose of this class is persisting the PublishAction bean to the database using the JPA / Hibernate framework defined in Tridion Content Delivery. The class implements the interface PublishActionDAO.java defined-above and extends class com.tridion.storage.persistence.JPABaseDAO.

The implementation class uses Spring framework annotations to declare itself as String-managed component. This helps Spring to auto-detect it and to register its corresponding Bean definition with the application:

@Component("JPAPublishActionDAO")

@Scope("prototype")

publicclass JPAPublishActionDAO extends JPABaseDAO implements PublishActionDAO {

 

Continue by defining the inherited constructors:

public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory, String storageName) {

       super(storageId, entityManagerFactory, storageName);

}

 

public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory,

              EntityManager entityManager, String storageName) {

       super(storageId, entityManagerFactory, entityManager, storageName);

}

 

Finally, implement each method defined in interface PublishActionDAO.

Putting it all together, the final implementation class looks like this:

package com.tridion.storage.extension.search;

 

/**

 * @author Mihai Cadariu

 */

@Component("JPAPublishActionDAO")

@Scope("prototype")

publicclass JPAPublishActionDAO extends JPABaseDAO implements PublishActionDAO {

 

       public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory, String storageName) {

              super(storageId, entityManagerFactory, storageName);

       }

 

       public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory,

                     EntityManager entityManager, String storageName) {

              super(storageId, entityManagerFactory, entityManager, storageName);

       }

 

       public PublishAction store(PublishAction publishAction) throws StorageException {

              PublishAction entity = (PublishAction) super.create(publishAction);

              return entity;

       }

 

       public PublishAction findByPrimaryKey(long publishActionId) throws StorageException {

              StringBuilder queryBuilder = new StringBuilder();

              queryBuilder.append("select c from PublishAction c where c.id = :id");

 

              Map queryParams = new HashMap();

              queryParams.put("id", Long.valueOf(publishActionId));

 

              return (PublishAction) super.executeQuerySingleResult(queryBuilder.toString(), queryParams);

       }

 

       public PublishAction update(PublishAction publishAction) throws StorageException {

              PublishAction existingPublishAction = findByPrimaryKey(publishAction.getId());

 

              if (existingPublishAction != null) {

                     return (PublishAction) super.update(publishAction);

              } else {

                     thrownew StorageException("Could not find publish action in storage to update!!!");

              }

       }

 

       publicvoid remove(long publishActionId) throws StorageException {

              PublishAction foundPublishAction = findByPrimaryKey(publishActionId);

              if (foundPublishAction != null) {

                     super.remove(foundPublishAction);

              }

       }

}

Move on to Part 3: Configuration and Testing