Hello,
I have a working
JBoss web app that interacts with a MySQL backend loaded with a biological dataset that changes once every couple months at most (aside from user data, which doesn't impinge upon my question). The data are organized categorized according to an outside schema, which I'd like to represent as a tree by extending the DefaultMutableTreeNode on the node ECObjects (data 'points') from the database.
So far, so good. By firing an org.apache.struts.action.Action which calls the BinDirectory constructor (see code below), the webapp can successfully construct and display the tree appropriately. But since this is a relatively resource-intensive process, I'd like to instantiate at most a handful of these as static Objects (
Servlets?) and provide read-only access to them from other areas of the web application.
The question is: How to do it? I'm including my web.xml and two util classes that are involved for your review.
Feedback greatly appreciated.
<!------- WEB.XML ---------->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>98</load-on-startup>
</servlet>
<servlet>
<servlet-name>directory</servlet-name>
<servlet-class>webutils.BinDirectory</servlet-class>
<load-on-startup>99</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Open</display-name>
<web-resource-collection>
<web-resource-name>Open</web-resource-name>
<url-pattern>/*</url-pattern>
<url-pattern>/images/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/js/*</url-pattern>
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/xhtml/*</url-pattern>
<url-pattern>/about.jsp</url-pattern>
<url-pattern>/logout.jsp</url-pattern>
<url-pattern>/purchaseInfo.jsp</url-pattern>
<url-pattern>/contactInfo.jsp</url-pattern>
<url-pattern>/activationOptions.do</url-pattern>
<url-pattern>/activationOptions.jsp</url-pattern>
<url-pattern>/agreement.do</url-pattern>
<url-pattern>/agreement.jsp</url-pattern>
<url-pattern>/composeActivationEmail.do</url-pattern>
<url-pattern>/sendEmail.do</url-pattern>
<url-pattern>/register.jsp</url-pattern>
<url-pattern>/register.do</url-pattern>
<url-pattern>/activateUser.do</url-pattern>
<url-pattern>/logout.jsp</url-pattern>
<url-pattern>/errorPage.jsp</url-pattern>
<url-pattern>/notFound.jsp</url-pattern>
<url-pattern>/comingSoon.jsp</url-pattern>
<url-pattern>/favicon.ico</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<display-name>level1</display-name>
<web-resource-collection>
<web-resource-name>Secure</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ActiveUser</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>login</realm-name>
<form-login-config>
<form-login-page>/loginform.jsp</form-login-page>
<form-error-page>/loginerror.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description>ActiveUser</description>
<role-name>ActiveUser</role-name>
</security-role>
<security-role>
<description>InactiveUser</description>
<role-name>InactiveUser</role-name>
</security-role>
<security-role>
<description>Administrator</description>
<role-name>Administrator</role-name>
</security-role>
<security-role>
<description>System</description>
<role-name>System</role-name>
</security-role>
<error-page>
<error-code>400</error-code>
<location>/index.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/errorPage.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/notFound.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errorPage.jsp</location>
</error-page>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
<!------------ BinDirectory.java -------------->
package webutils;
import moad.BinBean.Bin;
import moad.BinSessionHome;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.naming.NamingException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import java.rmi.RemoteException;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* <p/>
* User: Jason
* Date: Nov 9, 2004
* Time: 8:58:13 PM
* To change this template use File | Settings | File Templates.
*/
public final class BinDirectory extends HttpServlet{
public Log log = LogFactory.getFactory().getInstance(BinDirectory.class);
private static HashSet unmatched = new HashSet(1011, 100);
private static ECObject root = new ECObject(new Integer(0), new Integer(0), new Integer(0), new Integer(0));
private int size = 0;
public static ECObject getRoot() {
return root;
}
public void init(ServletConfig config) throws ServletException{
super.init(config);
try{
new BinDirectory();
} catch( Exception e ){}
}
public BinDirectory() throws NamingException, RemoteException, CreateException, FinderException {
Iterator myItr = ((BinSessionHome) moad.util.HomeFactory.getSessionHome("BinSessionEJB"))
.create().findAll().iterator();
while (myItr.hasNext()) { // add bins to the directory
Bin bin = (Bin) myItr.next();
if (bin.getEcNumber().indexOf("unmatched") != -1)
unmatched.add(bin); // unless they're unmatched
else if (bin.getEcNumber() != null){
size++;
addECObject(new ECObject(bin.getEcNumber(), bin.getId()));
}
}
}
public int getSize() {
return size;
}
private void addECObject(ECObject ecObject) {
ECObject parent = findOrCreateParent(ecObject);
parent.add(ecObject);
while ( !parent.equals(root) ){
ECObject grandparent = findOrCreateParent(parent);
grandparent.add(parent);
parent = grandparent;
}
}
private ECObject findOrCreateParent(ECObject ecObject) {
ECObject parent = ecObject.inferParent();
if ( parent != null && !parent.equals(root) ) {
Enumeration e = root.depthFirstEnumeration();
while (e.hasMoreElements()) { // search for it and return it if it exists
ECObject temp = ((ECObject) e.nextElement());
if (temp.equals( parent )){
// System.out.println("I am " + ecObject + " child of " + temp );
return temp;
}
}
return parent; // or return a new one
}
else if( parent.equals(root)){ // return the root
// System.out.println("I am " + ecObject + " child of root" );
return root;
}
else throw new NullPointerException(); // somethin ain't right
}
}
<!------------ ECObject.java ------------->
package webutils;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: Jason
* Date: Dec 14, 2004
* Time: 5:42:11 PM
* To change this template use File | Settings | File Templates.
*/
public final class ECObject extends DefaultMutableTreeNode implements Comparable {
private Integer first;
private Integer second;
private Integer third;
private Integer fourth;
private TreeSet kids = new TreeSet();
private Integer binId = new Integer(0);
private
String family;
private String subfamily;
public TreeSet getChildren() {
return kids;
}
ECObject(String ecNumber, Integer binId) {
super();
this.binId = binId;
StringTokenizer stok = new StringTokenizer(ecNumber, ".", false);
first = new Integer(stok.nextToken().trim());
second = enumerate(stok.nextToken().trim());
third = enumerate(stok.nextToken().trim());
try{
fourth = enumerate(stok.nextToken().trim());
} catch (NoSuchElementException nsee){
fourth = new Integer(0);
System.out.println("Servlet initialization error - can't find fourth" );
}
}
ECObject(Integer first, Integer second, Integer third, Integer fourth ) {
this.first = first;
this.second = second;
this.third = third;
this.fourth = fourth;
}
private Integer enumerate(String s) {
try {
return new Integer(s);
} catch (NumberFormatException nfe) {
return new Integer(0);
}
}
public Enumeration children() {
return Collections.enumeration(kids);
}
public void add(MutableTreeNode newChild) {
ECObject ec = (ECObject) newChild;
ec.setParent(this);
kids.add((ECObject) newChild);
}
public ECObject inferParent() {
Integer z = new Integer(0);
if (equals(new ECObject(z, z, z, z))) return null;
if (second.equals(new Integer(0))) return new ECObject(z, z, z, z);
if (third.equals(new Integer(0))) return new ECObject(first, z, z, z);
if (fourth.equals(new Integer(0))) return new ECObject(first, second, z, z);
if (isComplete()) return new ECObject(first, second, third, z);
return null;
}
public boolean isComplete() {
Integer z = new Integer(0);
return (!(fourth.equals(z) || third.equals(z) || second.equals(z) || first.equals(z)));
}
public String toString() {
String s = (second.equals(new Integer(0))) ? "-" : second.toString();
String t = (third.equals(new Integer(0))) ? "-" : third.toString();
String f = (fourth.equals(new Integer(0))) ? "-" : fourth.toString();
return first + "." + s + "." + t + "." + f;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ECObject)) return false;
final ECObject ecObject = (ECObject) o;
if (first == null && ecObject.getFirst() != null) return false;
if (first != null && !first.equals(ecObject.getFirst())) return false;
if (second == null && ecObject.getSecond() != null) return false;
if (second != null && !second.equals(ecObject.getSecond())) return false;
if (third == null && ecObject.getThird() != null) return false;
if (third != null && !third.equals(ecObject.getThird())) return false;
if (fourth == null && ecObject.getFourth() != null) return false;
if (fourth != null && !fourth.equals(ecObject.getFourth())) return false;
return true;
}
public int hashCode() {
int result;
result = (first != null ? first.hashCode() : 0);
result = 29 * result + (second != null ? second.hashCode() : 0);
result = 29 * result + (third != null ? third.hashCode() : 0);
result = 29 * result + (fourth != null ? fourth.hashCode() : 0);
return result;
}
public int compareTo(Object o) {
ECObject ec = (ECObject) o;
if (equals(ec)) return 0;
if (first.intValue() < ec.getFirst().intValue()) return -1;
if (second.intValue() < ec.getSecond().intValue()) return -1;
if (third.intValue() < ec.getThird().intValue()) return -1;
if (fourth.intValue() < ec.getFourth().intValue()) return -1;
return 1;
}
public Integer getFirst() {
return first;
}
public void setFirst(Integer first) {
this.first = first;
}
public Integer getSecond() {
return second;
}
public void setSecond(Integer second) {
this.second = second;
}
public Integer getThird() {
return third;
}
public void setThird(Integer third) {
this.third = third;
}
public Integer getFourth() {
return fourth;
}
public void setFourth(Integer fourth) {
this.fourth = fourth;
}
public Integer getBinId() {
return binId;
}
public void setBinId(Integer binId) {
this.binId = binId;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
public String getSubfamily() {
return subfamily;
}
public void setSubfamily(String subfamily) {
this.subfamily = subfamily;
}
public Object clone() {
return new ECObject(first, second, third, fourth);
}
public void classify() {
int f = getFirst().intValue();
int s = getSecond().intValue();
switch (f) {
case (1):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "oxidoreductases";
break;
}
case (2):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "";
break;
}
case (3):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "";
break;
}
case (4):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "";
break;
}
case (5):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "";
break;
}
case (6):
{
switch (s) {
case (1):
{
subfamily = "";
break;
}
default: subfamily="unassigned";
}
family = "";
break;
}
default: family = "unassigned";
}
}
}