Hello again:
I download the sources for Castor 0.9.4.2 and built a jar file with
debugging symbols turned on. I then let my application idle again
to get some more info.
Here is the exception I got this time:
Exception: java.lang.ArrayIndexOutOfBoundsException: 3
java.lang.ArrayIndexOutOfBoundsException: 3
at org.exolab.castor.persist.ClassMolder.load(ClassMolder.java:715)
at org.exolab.castor.persist.LockEngine.load(LockEngine.java:359)
at
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:64
9)
at org.exolab.castor.persist.QueryResults.fetch(QueryResults.java:229)
at
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImp
l.java:640)
at
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImp
l.java:623)
at admin.LoginCallback.checkLogin(LoginCallback.java:54)
at
com.jammconsulting.servlet.admin.AdminServlet.process(AdminServlet.java:89)
at
com.jammconsulting.servlet.admin.AdminServlet.doPost(AdminServlet.java:55)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Application
FilterChain.java:247)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterCh
ain.java:193)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.ja
va:260)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.ja
va:191)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180
)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.
java:170)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172
)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java
:174)
at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.connector.warp.WarpRequestHandler.handle(Unknown
Source)
at org.apache.catalina.connector.warp.WarpConnection.run(Unknown Source)
at java.lang.Thread.run(Thread.java:536)
Looking at line 715 in ClassMolder, it contains this code:
temp = fields[i];
This is in this loop:
for ( int i = 0; i < _fhs.length; i++ ) {
So, obviously, the fields array contains less objects than the _fhs array.
On line 687, I see this statement where the fields array is being filled in:
fields = (Object[]) locker.getObject( tx );
According to the comments, this is attempting to load the object from the
cache.
I dont know what to do next to try to figure this out.
Any guidance?
Thanks,
Neil.
--
Neil Aggarwal
JAMM Consulting, Inc. (972) 612-6056, http://www.JAMMConsulting.com
Custom Internet Development Websites, Ecommerce, Java, databases
> -----Original Message-----
> From: Neil Aggarwal [mailto:[EMAIL PROTECTED]]
> Sent: Tuesday, February 11, 2003 11:10 AM
> To: [EMAIL PROTECTED]
> Subject: [castor-dev] ArrayIndexOutOfBoundsException after application
> is idle for hours
>
>
> Hello:
>
> I get an ArrayIndexOutOfBoundsException when I leave my application
> alone for a couple of hours. It does not occur when the application first
> runs. Also, if I re-start the application, everything is OK again.
>
> Here is the exception:
> Exception: java.lang.ArrayIndexOutOfBoundsException: 3
> java.lang.ArrayIndexOutOfBoundsException: 3
> at org.exolab.castor.persist.ClassMolder.load(Unknown Source)
> at org.exolab.castor.persist.LockEngine.load(Unknown Source)
> at org.exolab.castor.persist.TransactionContext.load(Unknown Source)
> at org.exolab.castor.persist.QueryResults.fetch(Unknown Source)
> at
> org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(Unknown
> Source)
> at
> org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(Unknown
> Source)
> at admin.LoginCallback.checkLogin(LoginCallback.java:54)
> at
> com.jammconsulting.servlet.admin.AdminServlet.process(AdminServlet
> .java:89)
> at
> com.jammconsulting.servlet.admin.AdminServlet.doPost(AdminServlet.java:55)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(A
> pplication
> FilterChain.java:247)
> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(Applicati
> onFilterCh
> ain.java:193)
> at
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapp
> erValve.ja
> va:260)
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:643)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.
> java:480)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
> at
> org.apache.catalina.core.StandardContextValve.invoke(StandardConte
> xtValve.ja
> va:191)
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:643)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.
> java:480)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
> at
> org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
> at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValv
> e.java:180
> )
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:643)
> at
> org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispat
> cherValve.
> java:170)
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:641)
> at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValv
> e.java:172
> )
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:641)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.
> java:480)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
> at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngine
> Valve.java
> :174)
> at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValveCon
> text.invok
> eNext(StandardPipeline.java:643)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.
> java:480)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
> at
> org.apache.catalina.connector.warp.WarpRequestHandler.handle(Unknown
> Source)
> at
> org.apache.catalina.connector.warp.WarpConnection.run(Unknown Source)
> at java.lang.Thread.run(Thread.java:536)
>
> This happens all the time with my application, but I have not been able to
> repeat it in
> a test case I tried to come up with. The code is essentially
> identical but
> the same error
> does not occur.
>
> Here is the relevant code in the LoginCallback class which throws the
> exception:
>
> Database db = null;
> try {
> // Get the database
> db = DbUtil.getDatabase();
>
> // See if there is an administrator object with the given login and
> password
> OQLQuery query = db.getOQLQuery("select a from
> "+Administrator.class.getName()+" a where a.emailAddress LIKE $1 and
> a.encryptedPassword = $2" );
> query.bind(login);
> query.bind(StringUtils.encrypt(password));
> QueryResults results = query.execute();
> if( results.hasMore() ) {
> Administrator administrator = (Administrator) results.next();
> req.getSession().setAttribute(ParameterNames.LOGIN,administrator);
> return LOGIN_OK;
> }
>
> // If we are still here, it means the login was not found
> return LOGIN_FAILED;
>
> } catch( Exception e ) {
> // Notify the admin
> ServletUtil.notifyInternalError(req,e,Constants.ADMIN_EMAIL);
> return LOGIN_ERROR;
> } finally {
> if( db != null ) {
> try {
> db.rollback();
> db.close();
> } catch( Exception e ) {
> // Notify the admin
> ServletUtil.notifyInternalError(req,e,Constants.ADMIN_EMAIL);
> }
> }
> }
>
> Line 54 in the code above is:
> if( results.hasMore() ) {
>
> Why should hasMore() throw an ArrayIndexOutOfBoundsException?
>
> My theory is that there are multiple Administrator and Subscriber
> objects in
> the database. Administrator extends Subscriber and somewhere in the code,
> Castor thinks it has more Administrator objects than it really
> does because
> of the subclass relationship.
>
> I am using Castor 0.9.4.2 on Redhat Linux 8.0 with Apache 2.0.43, Tomcat
> 4.1.18,
> and MySQL 3.32.55.
>
> Here is my database.xml file:
> <?xml version="1.0" encoding="UTF-8"?>
>
> <!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version
> 1.0//EN" "http://castor.exolab.org/jdo-conf.dtd">
>
> <database name="newsletter" engine="mysql">
> <driver class-name="com.mysql.jdbc.Driver"
> url="jdbc:mysql://localhost:3306/newsletter">
> <param name="user" value="newsletter" />
> <param name="password" value="[removed]" />
> </driver>
> <mapping href="mapping.xml"/>
> </database>
>
> Here is the mapping.xml file:
> <?xml version="1.0"?>
>
> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
> "http://castor.exolab.org/mapping.dtd">
>
> <mapping>
>
> <!--
> =================================================================== -->
> <!-- Mapping for class persistent.Subscriber -->
> <!--
> =================================================================== -->
>
> <class name="persistent.Subscriber"
> identity="id"
> access="shared"
> key-generator="MAX"
> auto-complete="false">
> <map-to table="Subscriber" />
> <cache-type type="count-limited" />
>
> <field name="emailAddress"
> type="java.lang.String"
> required="true"
> get-method="getEmailAddress"
> set-method="setEmailAddress">
> <sql name="emailAddress"
> type="char" />
> </field>
>
> <field name="id"
> type="integer"
> get-method="getId"
> set-method="setId">
> <sql name="id"
> type="integer" />
> </field>
>
> <field name="subscriptionDate"
> type="java.util.Date"
> required="true"
> get-method="getSubscriptionDate"
> set-method="setSubscriptionDate">
> <sql name="subscriptionDate"
> type="date" />
> </field>
>
> <field name="subscriptionSource"
> type="java.lang.String"
> required="true"
> get-method="getSubscriptionSource"
> set-method="setSubscriptionSource">
> <sql name="subscriptionSource"
> type="char" />
> </field>
>
> </class>
>
> <!--
> =================================================================== -->
> <!-- Mapping for class persistent.Administrator -->
> <!--
> =================================================================== -->
>
> <class name="persistent.Administrator"
> identity="id"
> access="shared"
> extends="persistent.Subscriber"
> key-generator="MAX"
> auto-complete="false">
> <map-to table="Administrator" />
> <cache-type type="count-limited" />
>
> <field name="encryptedPassword"
> type="java.lang.String"
> required="true"
> get-method="getEncryptedPassword"
> set-method="setEncryptedPassword">
> <sql name="encryptedPassword"
> type="char" />
> </field>
>
> <field name="id"
> type="integer"
> get-method="getId"
> set-method="setId">
> <sql name="id"
> type="integer" />
> </field>
>
> </class>
>
> <!--
> =================================================================== -->
> <!-- Mapping for class persistent.NewsletterContent -->
> <!--
> =================================================================== -->
>
> <class name="persistent.NewsletterContent"
> identity="id"
> access="shared"
> key-generator="MAX"
> auto-complete="false">
> <map-to table="NewsletterContent" />
> <cache-type type="count-limited" />
>
> <field name="active"
> type="boolean"
> get-method="getActive"
> set-method="setActive">
> <sql name="active"
> type="bit" />
> </field>
>
> <field name="content"
> type="java.lang.String"
> required="true"
> get-method="getContent"
> set-method="setContent">
> <sql name="content"
> type="clob" />
> </field>
>
> <field name="heading"
> type="java.lang.String"
> required="true"
> get-method="getHeading"
> set-method="setHeading">
> <sql name="heading"
> type="char" />
> </field>
>
> <field name="id"
> type="integer"
> get-method="getId"
> set-method="setId">
> <sql name="id"
> type="integer" />
> </field>
>
> <field name="newsletterDate"
> type="java.util.Date"
> required="true"
> get-method="getNewsletterDate"
> set-method="setNewsletterDate">
> <sql name="newsletterDate"
> type="date" />
> </field>
>
> </class>
>
> </mapping>
>
> Here is my database schema:
> DROP TABLE IF EXISTS Administrator;
> CREATE TABLE Administrator (
> id int PRIMARY KEY,
> encryptedPassword varchar(255) NOT NULL,
> INDEX (encryptedPassword)
> ) TYPE = InnoDB;
>
> DROP TABLE IF EXISTS NewsletterContent;
> CREATE TABLE NewsletterContent (
> id int PRIMARY KEY,
> newsletterDate DATE NOT NULL,
> heading varchar(255),
> content longtext,
> active bool
> ) TYPE = InnoDB;
>
> DROP TABLE IF EXISTS Subscriber;
> CREATE TABLE Subscriber (
> id int PRIMARY KEY,
> emailAddress varchar(255) NOT NULL,
> subscriptionDate DATE NOT NULL,
> subscriptionSource varchar(255) NOT NULL,
> INDEX (emailAddress)
> ) TYPE = InnoDB;
>
> Here is the source for the Subscriber class:
> /*
> * Subscriber.java
> */
> package persistent;
>
> import com.jammconsulting.db.castor.*;
> import com.jammconsulting.db.exceptions.*;
> import java.util.*;
>
> /**
> * Class to hold information on a newsletter subscriber
> *
> * @castor:class table="Subscriber" id="id" key-generator="MAX"
> */
> public class Subscriber extends DbObject {
> /**
> * The subscriber's email address
> */
> private String emailAddress;
> /**
> * The date this user subscribed
> */
> private Date subscriptionDate = new Date();
> /**
> * How we got this user into the newsletter
> */
> private String subscriptionSource;
>
> /**
> * Get the id
> *
> * @castor:field type="integer" set-method="setId"
> * @castor:field-sql name="id" type="integer"
> */
> public int getId() {
> return super.getId();
> }
> /**
> * Set the id
> */
> public void setId(int id) {
> super.setId(id);
> }
>
> /**
> * Get the emailAddress
> *
> * @castor:field required="true" set-method="setEmailAddress"
> * @castor:field-sql type="char" name="emailAddress"
> */
> public String getEmailAddress() {
> return emailAddress;
> }
>
> /**
> * Set the emailAddress
> */
> public void setEmailAddress(String emailAddress) {
> this.emailAddress = emailAddress;
> }
>
> /**
> * Get the subscriptionDate
> *
> * @castor:field required="true" set-method="setSubscriptionDate"
> * @castor:field-sql type="date" name="subscriptionDate"
> */
> public Date getSubscriptionDate() {
> return subscriptionDate;
> }
>
> /**
> * Set the subscriptionDate
> */
> public void setSubscriptionDate(Date subscriptionDate) {
> this.subscriptionDate = subscriptionDate;
> }
>
> /**
> * Get the subscriptionSource
> *
> * @castor:field required="true" set-method="setSubscriptionSource"
> * @castor:field-sql type="char" name="subscriptionSource"
> */
> public String getSubscriptionSource() {
> return subscriptionSource;
> }
>
> /**
> * Set the subscriptionSource
> */
> public void setSubscriptionSource(String subscriptionSource) {
> this.subscriptionSource = subscriptionSource;
> }
>
> /**
> * Validate this object
> */
> public void validate() throws ValidationException {
> if( (emailAddress==null) || (emailAddress.length()<=0) )
> throw new ValidationException( "You must give an email address" );
>
> // Make sure the email address has an '@' in it
> int atIndex = emailAddress.indexOf('@');
> if( atIndex <= 0 )
> throw new ValidationException("Your email address appears to be
> invalid");
>
> // Make sure the email address has an '.' in it after the '@'
> int dotIndex = emailAddress.lastIndexOf('.');
> if( dotIndex <= atIndex )
> throw new ValidationException("Your email address appears to be
> invalid");
> }
> }
>
> Here is the source for the Administrator class:
> /*
> * Administrator.java
> */
> package persistent;
>
> import com.jammconsulting.utils.*;
> import java.security.*;
>
> /**
> * Class to hold information on an administrator
> *
> * @castor:class table="Administrator" extends="persistent.Subscriber"
> id="id"
> */
> public class Administrator extends Subscriber {
> /**
> * The administrator's encyprted password
> */
> private String encryptedPassword;
>
> /**
> * Get the id
> *
> * @castor:field type="integer" set-method="setId"
> * @castor:field-sql name="id" type="integer"
> */
> public int getId() {
> return super.getId();
> }
> /**
> * Set the id
> */
> public void setId(int id) {
> super.setId(id);
> }
>
> /**
> * Get the encryptedPassword
> *
> * @castor:field required="true" set-method="setEncryptedPassword"
> * @castor:field-sql type="char" name="encryptedPassword"
> */
> public String getEncryptedPassword() {
> return encryptedPassword;
> }
>
> /**
> * Set the encryptedPassword
> */
> public void setEncryptedPassword(String encryptedPassword) {
> this.encryptedPassword = encryptedPassword;
> }
>
> /**
> * Set the administrator's password with an unencrypted password.
> * The password will be encrypted before it is set.
> */
> public void setPassword(String password) throws
> NoSuchAlgorithmException {
> setEncryptedPassword(StringUtils.encrypt(password));
> }
> }
>
> Any ideas?
> Is there anything else you need?
>
> Thanks,
> Neil.
>
> --
> Neil Aggarwal
> JAMM Consulting, Inc. (972) 612-6056, http://www.JAMMConsulting.com
> Custom Internet Development Websites, Ecommerce, Java, databases
>
> -----------------------------------------------------------
> If you wish to unsubscribe from this mailing, send mail to
> [EMAIL PROTECTED] with a subject of:
> unsubscribe castor-dev
-----------------------------------------------------------
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
unsubscribe castor-dev