locallib classes not loading

To override the classes that would run on the ATG server, one simply copies your new classes into the locallib directory under the correct directory which corresponds to the package. To learn more, Modifying the Environment Settings.

However on an ATG Dynamo 4.5.1 server running on FreeBSD I found the locallib classes were not loading no matter how many times I restarted the ATG Dynamo server. I realized finally by accident that the reason these classes weren’t being loaded was because another ATG Dynamo server was running and because of this the Java process was not releasing its understanding of the CLASSPATH. Only after killing the second ATG Dynamo server process was I finally able to get the ATG Dynamo server to load the new classes.

JSP Dynamo Request Retrieval

In JHTML pages, the request object is of class DynamoHttpServletRequest which has many methods that are not part of the HttpServletRequest interface including the very useful resolveName method for looking up components in Nucleus.

In JSP pages on ATG there is no guarantee that the request object is of class DynamoHttpServletRequest. According to the JSP specification the request object always implements the HttpServletRequest interface.

If you need to get the DynamoHttpServletRequest do something like this:

DynamoHttpServletRequest dynRequest  = atg.servlet.ServletUtil.getDynamoRequest(request);

If you need to get a PortalServletRequest do something like this:

PortalServletRequest portalRequest = (PortalServletRequest) request.getAttribute(atg.portal.servlet.Attributes.PORTALSERVLETREQUEST);

Shell Tricks

To search for all files that contain a certain string use find with the -exec flag. For example:

find . -name "*.haystack" -type f -exec grep -l needle "{}" ";"

grep -l flag tells grep to output only the file name if there is a match.
"{}" is replaced iteratively by the file names found.
";" terminates the command.

JDBC Optimization for Populating a Table

Today I was trying to determine how to optimize the populating of a table. I was using ATG Relational Views which took 3.5 minutes to add 6000 lines to a table.

After googling for awhile I learned how to do this using JDBC directly and was able to do the same populating in 0.14 minutes. That’s quite a performance improvement.

It would be interesting to contract the performance differences using ATG’s repository implementation but right now I am developing on ATG 4.5.1 so I can’t.

These are the links to the sites I used to educate me on PreparedStatement‘s and batching.

ONJava.com: An Introduction to JDBC, Part 3
JavaWorld.com: Overpower the Prepared Statement
PreciseJava.com: Best practices to improve performance in JDBC
DBA-oracle.com: Optimize Oracle INSERT performance

JHTML Structure

The typical JHTML file is structured like this.

<importbean bean="/atg/dynamo/service/jdbc/RelationalViewDroplet">

<nucleus type=import>
  /atg/dynamo/droplet/ForEach
  /atg/dynamo/droplet/Switch
</nucleus>

<java type="import">
  java.util.*
  java.net.*
</java>

<java>
  List ll = (List) request.resolveName("/betweengo/BigList");
</java>

Find a class’s runtime origin

JavaWorld has a great article on finding a class’s runtime origin called Back to your Class roots. Below is the highly useful getClassLocation method from the article.

/**
 * Given a Class object, attempts to find its .class location.
 * Use for testing/debugging only.
 * 
 * @return URL that points to the class definition; null if not found
 */
public static URL getClassLocation (final Class cls) {
  if (cls == null) throw new IllegalArgumentException ("null input");
  
  URL result = null;
  final String clsAsResource = cls.getName ().replace ('.', '/').concat (".class");
  
  final ProtectionDomain pd = cls.getProtectionDomain ();
  // java.lang.Class contract does not specify if 'pd' can ever be
  // null; it is not the case for Sun's implementations, but guard
  // against null just in case:
  if (pd != null) {
    final CodeSource cs = pd.getCodeSource ();
    // 'cs' can be null depending on the classloader behavior:
    if (cs != null) result = cs.getLocation ();
    
    if (result != null) {
      // Convert a code source location into a full class file location
      // for some common cases:
      if ("file".equals (result.getProtocol ())) {
        try {
          if (result.toExternalForm ().endsWith (".jar") ||
            result.toExternalForm ().endsWith (".zip")) 
            result = new URL ("jar:".concat (result.toExternalForm ())
              .concat("!/").concat (clsAsResource));
          else if (new File (result.getFile ()).isDirectory ())
            result = new URL (result, clsAsResource);
        }
        catch (MalformedURLException ignore) {}
      }
    }
  }
  
  if (result == null) {
    // Try to find 'cls' definition as a resource; this is not
    // documented to be legal, but Sun's implementations seem to allow
    // this:
    final ClassLoader clsLoader = cls.getClassLoader ();
    
    result = clsLoader != null ?
      clsLoader.getResource (clsAsResource) :
      ClassLoader.getSystemResource (clsAsResource);
  }
  
  return result;
}

ACC not connecting

If you cannot connect to a site using the ACC try the following.

  1. use the host name instead of the IP address
  2. check that you are using the correct RMI port
  3. telnet to the site using the RMI port and see if you can connect
  4. check the ACC output window to see if there were any exceptions. if there was an UnknownHostException then try adding the host to your hosts file to fix the problem

Note: The host name you use should be the same as the java.rmi.server.hostname Java argument that is set in the server’s postEnvironment.sh.
JAVA_ARGS="${JAVA_ARGS} -Djava.rmi.server.hostname=kimcityqa"