You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Sean Dockery <do...@gmail.com> on 2005/12/23 17:03:09 UTC

IllegalAccessException expected all the time, but only occurs sometimes. Why?

I have a TestCase as follows...

package example;

import java.util.Date;

import junit.framework.TestCase;

public class JavaBeanTest extends TestCase {

 public JavaBeanTest(String testName) {
  super(testName);
 }

 public void testThrowawayCopy() throws Exception {
  // setup
  final JavaBean bean = new JavaBean();
  bean.setId(1L);
  bean.setName("hello");
  // exercise
  final JavaBean copy = bean.throwawayCopy();
  bean.setExpired(new Date());
  copy.setId(2L);
  copy.setName("world");
  // verify
  assertEquals("id affected by copy.setId(long) call", 2L, bean.getId());
  assertEquals("name not affected by copy.setName(String) call", "hello",
bean.getName());
  assertNotNull("expired has changed", bean.getExpired());

  assertEquals("id has changed", 2L, copy.getId());
  assertEquals("name has changed", "world", copy.getName());
  assertNull("expired not affected by bean.setExpired(Date) call",
copy.getExpired());
 }

 public static Test suite() {
  TestSuite suite = new TestSuite();
  Test test = new JavaBeanTest("testThrowawayCopy");
  for (int i = 0; i < 1000; i++) {
   suite.addTest(test);
  }
  return suite;
 }

}

...for which I have a JavaBean class as follows...

package example;

import java.lang.reflect.Method;
import java.util.Date;

public class JavaBean {

 private long id;
 private String name;
 private Date expired;

 public JavaBean() {
  // default constructor for JavaBean
 }

 public Date getExpired() {
  return expired;
 }

 public void setExpired(Date expired) {
  this.expired = expired;
 }

 public long getId() {
  return id;
 }

 public void setId(long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public JavaBean throwawayCopy() {
  return new ThrowawayJavaBean();
 }

 private final class ThrowawayJavaBean extends JavaBean {

  private boolean propagateId;

  private ThrowawayJavaBean() {
   copyProperties();
   propagateId = true;
  }

  private void copyProperties() {
   try {
    Method[] methods = JavaBean.this.getClass().getDeclaredMethods();
    for (int i = 0; i < methods.length; i++) {
     final Method source = methods[i];
     if (source.getName().startsWith("get")) {
      Method target = getClass().getMethod("set" +
source.getName().substring(3), new Class[] { source.getReturnType() });
      target.invoke(this, new Object[] { source.invoke(JavaBean.this, new
Object[] {}) });
     }
    }
   } catch (Exception e) {
    throw unchecked(e);
   }
  }

  public void setId(long id) {
   super.setId(id);

   if (propagateId) {
    JavaBean.this.setId(id);
   }
  }

  private RuntimeException unchecked(Exception e) {
   if (e instanceof RuntimeException) {
    return (RuntimeException) e;
   }
   return new RuntimeException(e);
  }

 }

}


This code has been adapted from some code in a production application at my
work.  The production code actually uses Spring's
BeanUtils.copyProperties(Object source, Object target) method in the
ThrowawayJavaBean constructor, but we should be accomplishing the same thing
by using reflection directly.

As you can see, the ThrowawayJavaBean class is a *private* nested class.
During load tests of the production application, the production code
(running in Tomcat) *sometimes* experiences an IllegalAccessException due to
the fact that we're using reflection against a private nested class.  The
problem has never occurred when the visibility of the nested class is
public.  Additionally, I have *never* seen the exception occur in the JUnit
TestRunner with neither the code I have presented above, nor the production
code itself.

My confusion lies with the question of why the IllegalAccessException occurs
only infrequently in the production code running under Tomcat instead of
always occurring.  That is, why doesn't (wouldn't) it happen all the
time--for example, in my TestCase?

Thanks for your time.





---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: IllegalAccessException expected all the time, but only occurs sometimes. Why?

Posted by Sean Dockery <do...@gmail.com>.
I found this on the web that seems to explain why the problem is
occurring...

http://opensource2.atlassian.com/projects/spring/browse/SPR-1518

"Sean Dockery" <do...@gmail.com> wrote in message 
news:doh743$23l$1@sea.gmane.org...
>I have a TestCase as follows...
>
> package example;
>
> import java.util.Date;
>
> import junit.framework.TestCase;
>
> public class JavaBeanTest extends TestCase {
>
> public JavaBeanTest(String testName) {
>  super(testName);
> }
>
> public void testThrowawayCopy() throws Exception {
>  // setup
>  final JavaBean bean = new JavaBean();
>  bean.setId(1L);
>  bean.setName("hello");
>  // exercise
>  final JavaBean copy = bean.throwawayCopy();
>  bean.setExpired(new Date());
>  copy.setId(2L);
>  copy.setName("world");
>  // verify
>  assertEquals("id affected by copy.setId(long) call", 2L, bean.getId());
>  assertEquals("name not affected by copy.setName(String) call", "hello",
> bean.getName());
>  assertNotNull("expired has changed", bean.getExpired());
>
>  assertEquals("id has changed", 2L, copy.getId());
>  assertEquals("name has changed", "world", copy.getName());
>  assertNull("expired not affected by bean.setExpired(Date) call",
> copy.getExpired());
> }
>
> public static Test suite() {
>  TestSuite suite = new TestSuite();
>  Test test = new JavaBeanTest("testThrowawayCopy");
>  for (int i = 0; i < 1000; i++) {
>   suite.addTest(test);
>  }
>  return suite;
> }
>
> }
>
> ...for which I have a JavaBean class as follows...
>
> package example;
>
> import java.lang.reflect.Method;
> import java.util.Date;
>
> public class JavaBean {
>
> private long id;
> private String name;
> private Date expired;
>
> public JavaBean() {
>  // default constructor for JavaBean
> }
>
> public Date getExpired() {
>  return expired;
> }
>
> public void setExpired(Date expired) {
>  this.expired = expired;
> }
>
> public long getId() {
>  return id;
> }
>
> public void setId(long id) {
>  this.id = id;
> }
>
> public String getName() {
>  return name;
> }
>
> public void setName(String name) {
>  this.name = name;
> }
>
> public JavaBean throwawayCopy() {
>  return new ThrowawayJavaBean();
> }
>
> private final class ThrowawayJavaBean extends JavaBean {
>
>  private boolean propagateId;
>
>  private ThrowawayJavaBean() {
>   copyProperties();
>   propagateId = true;
>  }
>
>  private void copyProperties() {
>   try {
>    Method[] methods = JavaBean.this.getClass().getDeclaredMethods();
>    for (int i = 0; i < methods.length; i++) {
>     final Method source = methods[i];
>     if (source.getName().startsWith("get")) {
>      Method target = getClass().getMethod("set" +
> source.getName().substring(3), new Class[] { source.getReturnType() });
>      target.invoke(this, new Object[] { source.invoke(JavaBean.this, new
> Object[] {}) });
>     }
>    }
>   } catch (Exception e) {
>    throw unchecked(e);
>   }
>  }
>
>  public void setId(long id) {
>   super.setId(id);
>
>   if (propagateId) {
>    JavaBean.this.setId(id);
>   }
>  }
>
>  private RuntimeException unchecked(Exception e) {
>   if (e instanceof RuntimeException) {
>    return (RuntimeException) e;
>   }
>   return new RuntimeException(e);
>  }
>
> }
>
> }
>
>
> This code has been adapted from some code in a production application at 
> my
> work.  The production code actually uses Spring's
> BeanUtils.copyProperties(Object source, Object target) method in the
> ThrowawayJavaBean constructor, but we should be accomplishing the same 
> thing
> by using reflection directly.
>
> As you can see, the ThrowawayJavaBean class is a *private* nested class.
> During load tests of the production application, the production code
> (running in Tomcat) *sometimes* experiences an IllegalAccessException due 
> to
> the fact that we're using reflection against a private nested class.  The
> problem has never occurred when the visibility of the nested class is
> public.  Additionally, I have *never* seen the exception occur in the 
> JUnit
> TestRunner with neither the code I have presented above, nor the 
> production
> code itself.
>
> My confusion lies with the question of why the IllegalAccessException 
> occurs
> only infrequently in the production code running under Tomcat instead of
> always occurring.  That is, why doesn't (wouldn't) it happen all the
> time--for example, in my TestCase?
>
> Thanks for your time. 




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org