ATG custom property descriptor to change data upon retrieving and persisting property

While coming up with a soon to be posted simple example of using the ATG stack to create an order, I found that using the encrypted credit number stored in the DPS_USER_CREDIT_CARD table was not usable upon checkout, as it did not meet the 16 character requirement and algorithm for a valid credit card number.

This is when I found that a custom property descriptor can be created to change data when fetched from the repository (and ultimately the database, in this case), as well as when it written/persisted back to the repository/database.

This post will provide a simple example of doing this.

For a complete example, we first create our table in the database:

create table core.mytab (id varchar2(254),
                                  col1 varchar2(254),
                                  col2 number(0)
                                  primary key (id)
                                 );
insert into core.mytab values(‘foo’,’Steve’,’1’);
commit;

We then create our properties file for our repository.

$class=atg.adapter.gsa.GSARepository
$scope=global
repositoryName=MyRepository
definitionFiles=/repository/myrepo.xml
dataSource=/atg/dynamo/service/jdbc/JTDataSource

XMLToolsFactory=/atg/dynamo/service/xml/XMLToolsFactory
transactionManager=/atg/dynamo/transaction/TransactionManager
idGenerator=/atg/dynamo/service/IdGenerator
lockManager=/atg/dynamo/service/ClientLockManager

cacheSwitchHot=false

Next, we create our java class to both write as well as read from the repository.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import atg.servlet.*;
import atg.repository.*;
import atg.repository.rql.*;
import atg.adapter.gsa.query.*;
import atg.nucleus.*;

public class getMyTab extends GenericService {
  public getMyTab() {}
  public void updateIt() {
    try {
      vlogInfo("started getMyTab()");
      MutableRepository repo = (MutableRepository)Nucleus.getGlobalNucleus().resolveName("/repository/MyRepository");
      RepositoryView view = repo.getView("mytab");
      RqlStatement rql = RqlStatement.parseRqlStatement("id = ?0");
      Object params[] = new Object[1];
      params[0] = new String("foo");
      RepositoryItem[] answer = rql.executeQuery(view,params);
      MutableRepositoryItem obj = repo.getItemForUpdate(answer[0].getRepositoryId(),answer[0].getItemDescriptor().getItemDescriptorName());
      obj.setPropertyValue("col1", "New value in mixed case");
      repo.updateItem(obj);
    }
    catch (Exception ce) {
      ce.printStackTrace();
    }
  }
  public void callIt() {
    try {
      vlogInfo("started getMyTab()");
      MutableRepository repo = (MutableRepository)Nucleus.getGlobalNucleus().resolveName("/repository/MyRepository");
      RepositoryView view = repo.getView("mytab");
      Object params[] = new Object[0];
      Builder builder = (Builder)view.getQueryBuilder();
      String str = "select * from mytab";
      RepositoryItem[] items = view.executeQuery (builder.createSqlPassthroughQuery(str, params));
      view.executeQuery (builder.createSqlPassthroughQuery(str, params));
      if (items == null) {
        vlogInfo("id", "No items were found");
      }
      else {
        for (int i = 0; i < items.length; i++){
          System.out.print(items[i].getPropertyValue("id"));
          System.out.print(items[i].getPropertyValue("col1"));
          System.out.println(items[i].getPropertyValue("col2"));
        }
      }
    }
    catch (Exception ce) {
      ce.printStackTrace();
    }
  }
}

Finally, we create our xml mapping file to map our component properties to our database table columns.






  
Test Repository Steve Howard 1

Before we go any further, note the property type of myEncryptDecrypt. This is our custom repository item descriptor. As you may expect, this is a java class which extends the GSAPropertyDescriptor class.

In our simple test case, we encrypt the value by converting it to upper case upon writing (tricky, eh? :)), and convert it to lower case when we fetch it from the repository. This simulates an encryption/decryption of a credit card used during purchase.

import atg.adapter.gsa.*;
import atg.core.util.*;
import atg.nucleus.*;
import atg.repository.*;

public class myEncryptDecrypt extends GSAPropertyDescriptor {
  public myEncryptDecrypt() {
    super();
  }

  public boolean isQueryable() {
    return false;
  }

  public void setPropertyValue(RepositoryItemImpl pItem, Object pValue) {
    try {
      super.setPropertyValue(pItem, pValue.toString().toUpperCase());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public Object getPropertyValue(RepositoryItemImpl pItem, Object pValue) {
    try {
      return super.getPropertyValue(pItem, pValue.toString().toLowerCase());
    }
    catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}

The java class above does not require a properties file, as it is only ever referenced by the repository during its normal course of operation.

Finally, we need to instruct ATG to load this repository upon startup. Add the following to a file named ContentRepositories.properties, located in localconfig/atg/registry under your ATG-Data directory.

Restart your application server.

initialRepositories+=/repository/MyRepository

In our test, we first show the value in the database is 'Steve', as we originally inserted it.

SQL> select * from core.mytab;

ID                   COL1                       COL2
-------------------- -------------------- ----------
foo                  Steve                         1

SQL>

When we execute the callIt() method in our getMyTab{} class (via an invoke method in dynamo administration on the component), we see it is converted to lower case, as we expected.

15:25:26,102 INFO  [MyRepository] SQL Repository startup complete
15:25:26,131 INFO  [STDOUT] foo
15:25:26,131 INFO  [STDOUT] steve
15:25:26,132 INFO  [STDOUT] 1

After we call our updateIt() method in our getMyTab{} class (once again, via an invoke method button call in dynamo admininstration), we see that our new value in the database is in upper case, even though we simply said update it to "New value in mixed case".

SQL> select * from core.mytab;

ID                   COL1                                 COL2
-------------------- ------------------------------ ----------
foo                  NEW VALUE IN MIXED CASE                 1

SQL>

1 comment for “ATG custom property descriptor to change data upon retrieving and persisting property

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.