A
Albretch
Hi,
as, I understand things, the JNDI can be used to share an object among different JVMs even from J2SE applications running on different machines. Right?
I need a relatively light object (that is why I am avoiding EJBs altogether) which would simply:
1._ poll a backend database at configurable periods, and if some data has changed
2._ update its internal state, which is then
3._ administered to and updated in a number of independent tomcat instances
Well, I did the following exp. and repeated it even compiling TC 5.5.5 from source in case I had to check it, but before I start diving deeper into what I think might be the reason for this anomaly, I want to check that I don't have a silly conf problem I haven't seen or there is something I am not quite understanding here.
Here is the method to my madness:
1._ I first downloaded TC's source code, 'built it' with ant, ran and tested it.
2._ Then I set up a number (3) of separate instances running from independent JVMs using the same files as in the original, plain installation, as describe in 1; by:
2.1_ setting up three independent directories, <...> /tc00/, /tc02/, and /tc04/ off the original installation
2.2_ just copying /conf/ and /bin/ from the original installation and dumping similar files on each dir described in 2.1
2.3_ changing then in each of the /conf/server.xml
2.3.1_ the Server port="8005"
2.3.2_ the non-SSL HTTP/1.1 Connector port="8080"
2.3.3_ the AJP 1.3 Connector port="8009" (<- will need it for later tinkering with Apache)
for all three independent instances, and
2.4_ making sure that the same absolute directory was used in the appBase attribute of the <Host name="localhost" . . . context
2.5_ then, making sure that the same;
2.5.1_ JAVA_HOME
2.5.2_ CATALINA_HOME
but different
2.5.3_ CATALINA_BASE
was set in the respective .../tcXX/bin/catalina.bat files (client wants me to 'try' windows 'too'), pointing to the respective .../tcXX
3._ I then ran all three instances and tested every thing was OK and scanned log
files for any errors, warnings, . . .
Everything seemed to be working just fine!
// - - - - - - - - - - - - - - - - - - - - -
Then I used the following slimmed down classes from example code sections in the jakarta JNDI howto, in order to illustrate my point.
Both classes were placed in the original installation's /common/classes/JNDITest/ directory
// - - - - - - - - - - - - - - - - - - - - -
package JNDITest;
public class JNDI00{
private int bar = 0;
private long lCreatTime = System.currentTimeMillis();
private String foo = "Default Foo, created at " + lCreatTime + "";
// __
public String getFoo() { return (this.foo); }
public void setFoo(String foo) { this.foo = foo; }
// __
public int getBar() { return (this.bar); }
public void setBar(int bar) { this.bar = bar; }
// __
public long getCreatTime() { return (lCreatTime); }
public void setCreatTime(long l){}
// __
}
// - - - - - - - - - - - - - - - - - - - - -
package JNDITest;
import java.util.*;
import javax.naming.*;
import javax.naming.spi.*;
public class JNDI00Factory implements ObjectFactory {
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws NamingException {
JNDI00 JNDI_Obj = new JNDI00();
Reference ref = (Reference) obj;
Enumeration addrs = ref.getAll();
while (addrs.hasMoreElements()) {
RefAddr addr = (RefAddr) addrs.nextElement();
String aSNm = addr.getType();
String value = (String) addr.getContent();
if (aSNm.equals("foo")) {
JNDI_Obj.setFoo(value);
} else if (aSNm.equals("bar")) {
try {
JNDI_Obj.setBar(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new NamingException("Invalid 'bar' value " + value);
}
}
}
return (JNDI_Obj);
}
}
// - - - - - - - - - - - - - - - - - - - - -
then included for each TC instance in the <GlobalNamingResources> element of $CATALINA_HOME/conf/server.xml
<Resource name="JNDICtxt/JNDI00Factory"
auth="Container"
type="JNDITest.JNDI00"
factory="org.apache.naming.factory.BeanFactory"
bar="23"/>
// - - - - - - - - - - - - - - - - - - - - -
in $CATALINA_HOME/conf/ Catalina/localhost/ROOT.xml
<ResourceLink name="jndiName"
global="JNDICtxt/JNDI00Factory"
type="JNDITest.JNDI00"/>
// - - - - - - - - - - - - - - - - - - - - -
and at the end of $CATALINA_HOME/webapps/ROOT/WEB-INF/web.xml
<resource-env-ref>
<description>JNDICtxt JNDI00Factory Test</description>
<resource-env-ref-name>jndiName</resource-env-ref-name>
<resource-env-ref-type>JNDITest.JNDI00</resource-env-ref-type>
</resource-env-ref>
// - - - - - - - - - - - - - - - - - - - - -
Then included right on /ROOT/index.jsp code segments looking like:
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="javax.naming.*" %>
<%@ page import="JNDItest.*" %>
<%@ page session="false" %>
<%!
// __
private Context initCtxt;
private Context envCtxt;
private JNDI00 JNDIObj;
// __
public void jspInit(){
// __ JNDI resources
String aBug = "<ul>";
// __
try{
initCtxt = new InitialContext();
envCtxt = (Context)initCtxt.lookup("java:comp/env");
// __
String aInitCtxt = initCtxt.toString();
String aEnvCtxt = envCtxt.toString();
// __
aBug += "<li>initCtxt: " + aInitCtxt + "</li>";
aBug += "<li>EnvCtxt: " + aEnvCtxt + "</li>";
// __
System.err.println(" initCtxt: |" + initCtxt + "|");
System.err.println(" envCtxt: |" + envCtxt + "|");
// __
System.err.println(" (new JNDI00()): |" + (new JNDI00()) + "|");
// __
String aCtxtURL = "JNDICtxt/JNDI00Factory";
aCtxtURL = "jndiName";
JNDIObj = (JNDI00)envCtxt.lookup(aCtxtURL);
System.err.println(" JNDIObj: |" + JNDIObj + "|");
if(JNDIObj != null){
System.err.println(" JNDIObj: |" + JNDIObj + "|");
System.err.println(" JNDIObj.getBar(): |" + (new Integer(JNDIObj.getBar())).toString() + "|");
System.err.println(" JNDIObj.getCreatTime(): |" + JNDIObj.getCreatTime() + "|");
System.err.println(" JNDIObj.getFoo(): |" + JNDIObj.getFoo() + "|");
// __
aBug += "<li>JNDIObj: |" + JNDIObj.toString() + "|</li>";
aBug += "<li>JNDIObj.getBar(): |" + (new Integer(JNDIObj.getBar())).toString() + "|</li>";
aBug += "<li>JNDIObj.getCreatTime(): |" + JNDIObj.getCreatTime() + "|</li>";
aBug += "<li>JNDIObj.getFoo(): |" + JNDIObj.getFoo() + "|</li>";
}
// __
aBug += "</ul>";
}catch(NamingException NmX){ NmX.printStackTrace(); }
// __
}// jspInit()
// __
public void JspDestroy(){}
%>
<%
// __ Response Headers
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
// __
%>
// - - - - - - - - - - - - - - - - - - - - -
and inside the actual page just after <body>
<%=aBug%>
// - - - - - - - - - - - - - - - - - - - - -
You will see each TC instance has its own instances of:
* javax.naming.InitialContext
* org.apache.naming.NamingContext
* JNDITest.JNDI00
What is it I am doing wrong here?
How could you achieve what I want, namely, read (kind of a singleton object) from different TOmcat instances?
as, I understand things, the JNDI can be used to share an object among different JVMs even from J2SE applications running on different machines. Right?
I need a relatively light object (that is why I am avoiding EJBs altogether) which would simply:
1._ poll a backend database at configurable periods, and if some data has changed
2._ update its internal state, which is then
3._ administered to and updated in a number of independent tomcat instances
Well, I did the following exp. and repeated it even compiling TC 5.5.5 from source in case I had to check it, but before I start diving deeper into what I think might be the reason for this anomaly, I want to check that I don't have a silly conf problem I haven't seen or there is something I am not quite understanding here.
Here is the method to my madness:
1._ I first downloaded TC's source code, 'built it' with ant, ran and tested it.
2._ Then I set up a number (3) of separate instances running from independent JVMs using the same files as in the original, plain installation, as describe in 1; by:
2.1_ setting up three independent directories, <...> /tc00/, /tc02/, and /tc04/ off the original installation
2.2_ just copying /conf/ and /bin/ from the original installation and dumping similar files on each dir described in 2.1
2.3_ changing then in each of the /conf/server.xml
2.3.1_ the Server port="8005"
2.3.2_ the non-SSL HTTP/1.1 Connector port="8080"
2.3.3_ the AJP 1.3 Connector port="8009" (<- will need it for later tinkering with Apache)
for all three independent instances, and
2.4_ making sure that the same absolute directory was used in the appBase attribute of the <Host name="localhost" . . . context
2.5_ then, making sure that the same;
2.5.1_ JAVA_HOME
2.5.2_ CATALINA_HOME
but different
2.5.3_ CATALINA_BASE
was set in the respective .../tcXX/bin/catalina.bat files (client wants me to 'try' windows 'too'), pointing to the respective .../tcXX
3._ I then ran all three instances and tested every thing was OK and scanned log
files for any errors, warnings, . . .
Everything seemed to be working just fine!
// - - - - - - - - - - - - - - - - - - - - -
Then I used the following slimmed down classes from example code sections in the jakarta JNDI howto, in order to illustrate my point.
Both classes were placed in the original installation's /common/classes/JNDITest/ directory
// - - - - - - - - - - - - - - - - - - - - -
package JNDITest;
public class JNDI00{
private int bar = 0;
private long lCreatTime = System.currentTimeMillis();
private String foo = "Default Foo, created at " + lCreatTime + "";
// __
public String getFoo() { return (this.foo); }
public void setFoo(String foo) { this.foo = foo; }
// __
public int getBar() { return (this.bar); }
public void setBar(int bar) { this.bar = bar; }
// __
public long getCreatTime() { return (lCreatTime); }
public void setCreatTime(long l){}
// __
}
// - - - - - - - - - - - - - - - - - - - - -
package JNDITest;
import java.util.*;
import javax.naming.*;
import javax.naming.spi.*;
public class JNDI00Factory implements ObjectFactory {
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws NamingException {
JNDI00 JNDI_Obj = new JNDI00();
Reference ref = (Reference) obj;
Enumeration addrs = ref.getAll();
while (addrs.hasMoreElements()) {
RefAddr addr = (RefAddr) addrs.nextElement();
String aSNm = addr.getType();
String value = (String) addr.getContent();
if (aSNm.equals("foo")) {
JNDI_Obj.setFoo(value);
} else if (aSNm.equals("bar")) {
try {
JNDI_Obj.setBar(Integer.parseInt(value));
} catch (NumberFormatException e) {
throw new NamingException("Invalid 'bar' value " + value);
}
}
}
return (JNDI_Obj);
}
}
// - - - - - - - - - - - - - - - - - - - - -
then included for each TC instance in the <GlobalNamingResources> element of $CATALINA_HOME/conf/server.xml
<Resource name="JNDICtxt/JNDI00Factory"
auth="Container"
type="JNDITest.JNDI00"
factory="org.apache.naming.factory.BeanFactory"
bar="23"/>
// - - - - - - - - - - - - - - - - - - - - -
in $CATALINA_HOME/conf/ Catalina/localhost/ROOT.xml
<ResourceLink name="jndiName"
global="JNDICtxt/JNDI00Factory"
type="JNDITest.JNDI00"/>
// - - - - - - - - - - - - - - - - - - - - -
and at the end of $CATALINA_HOME/webapps/ROOT/WEB-INF/web.xml
<resource-env-ref>
<description>JNDICtxt JNDI00Factory Test</description>
<resource-env-ref-name>jndiName</resource-env-ref-name>
<resource-env-ref-type>JNDITest.JNDI00</resource-env-ref-type>
</resource-env-ref>
// - - - - - - - - - - - - - - - - - - - - -
Then included right on /ROOT/index.jsp code segments looking like:
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page import="javax.naming.*" %>
<%@ page import="JNDItest.*" %>
<%@ page session="false" %>
<%!
// __
private Context initCtxt;
private Context envCtxt;
private JNDI00 JNDIObj;
// __
public void jspInit(){
// __ JNDI resources
String aBug = "<ul>";
// __
try{
initCtxt = new InitialContext();
envCtxt = (Context)initCtxt.lookup("java:comp/env");
// __
String aInitCtxt = initCtxt.toString();
String aEnvCtxt = envCtxt.toString();
// __
aBug += "<li>initCtxt: " + aInitCtxt + "</li>";
aBug += "<li>EnvCtxt: " + aEnvCtxt + "</li>";
// __
System.err.println(" initCtxt: |" + initCtxt + "|");
System.err.println(" envCtxt: |" + envCtxt + "|");
// __
System.err.println(" (new JNDI00()): |" + (new JNDI00()) + "|");
// __
String aCtxtURL = "JNDICtxt/JNDI00Factory";
aCtxtURL = "jndiName";
JNDIObj = (JNDI00)envCtxt.lookup(aCtxtURL);
System.err.println(" JNDIObj: |" + JNDIObj + "|");
if(JNDIObj != null){
System.err.println(" JNDIObj: |" + JNDIObj + "|");
System.err.println(" JNDIObj.getBar(): |" + (new Integer(JNDIObj.getBar())).toString() + "|");
System.err.println(" JNDIObj.getCreatTime(): |" + JNDIObj.getCreatTime() + "|");
System.err.println(" JNDIObj.getFoo(): |" + JNDIObj.getFoo() + "|");
// __
aBug += "<li>JNDIObj: |" + JNDIObj.toString() + "|</li>";
aBug += "<li>JNDIObj.getBar(): |" + (new Integer(JNDIObj.getBar())).toString() + "|</li>";
aBug += "<li>JNDIObj.getCreatTime(): |" + JNDIObj.getCreatTime() + "|</li>";
aBug += "<li>JNDIObj.getFoo(): |" + JNDIObj.getFoo() + "|</li>";
}
// __
aBug += "</ul>";
}catch(NamingException NmX){ NmX.printStackTrace(); }
// __
}// jspInit()
// __
public void JspDestroy(){}
%>
<%
// __ Response Headers
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
// __
%>
// - - - - - - - - - - - - - - - - - - - - -
and inside the actual page just after <body>
<%=aBug%>
// - - - - - - - - - - - - - - - - - - - - -
You will see each TC instance has its own instances of:
* javax.naming.InitialContext
* org.apache.naming.NamingContext
* JNDITest.JNDI00
What is it I am doing wrong here?
How could you achieve what I want, namely, read (kind of a singleton object) from different TOmcat instances?