• Bug
  • Status: Open
  • 2 Major
  • Resolution:
  • ehcache-core
  • cdennis
  • Reporter: andrey_a
  • February 13, 2012
  • 0
  • Watchers: 3
  • June 20, 2012

Attachments

Description

I make a simple 2 cache node simulation. First starting one node and then after some time starting another one. When second node starts it throws a warning during bootstrap:

21:10:39.404 [Bootstrap Thread for cache getOrtVisningListeHent] WARN n.s.e.d.RMIBootstrapCacheLoader - Error asynchronously performing bootstrap. The cause was: Error bootstrapping from remote peer. Message was: null net.sf.ehcache.distribution.RemoteCacheException: Error bootstrapping from remote peer. Message was: null at net.sf.ehcache.distribution.RMIBootstrapCacheLoader.doLoad(RMIBootstrapCacheLoader.java:176) at net.sf.ehcache.distribution.RMIBootstrapCacheLoader$BootstrapThread.run(RMIBootstrapCacheLoader.java:107) Caused by: java.lang.UnsupportedOperationException: null at net.sf.ehcache.store.CacheKeySet.toArray(CacheKeySet.java:121) at net.sf.ehcache.util.SetAsList.toArray(SetAsList.java:83) at java.util.ArrayList.(ArrayList.java:136) at net.sf.ehcache.distribution.RMICachePeer.getKeys(RMICachePeer.java:125) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:592) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport$1.run(Transport.java:154) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707) at java.lang.Thread.run(Thread.java:595) at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at net.sf.ehcache.distribution.RMICachePeer\_Stub.getKeys(Unknown Source) at net.sf.ehcache.distribution.RMIBootstrapCacheLoader.doLoad(RMIBootstrapCacheLoader.java:146) ... 1 common frames omitted

After that notmal replication between 2 nodes works fine. Ehcache configuration is attached to the issue.

Comments

Fiona OShea 2012-02-13

IS there an issue? thanks

Andrey Adamovich 2012-02-15

The problem seems to come from the fact that net.sf.ehcache.store.CacheKeySet does not implement one of the overloads of toArray method:

    /**
     * {@inheritDoc}
     */
    public <T> T[] toArray(final T[] a) {
        throw new UnsupportedOperationException();
    }

After I added an implementation and recompiled ehcache-core-2.5.1.jar the problem seems to go away. Here is the implementation:

    /**
     * {@inheritDoc}
     */
    public <T> T[] toArray(final T[] a) {
        Iterator<E> iterator = this.iterator();
        for (int i = 0; i < a.length; i++) {
            a[i] = (T) iterator.next();        
        }
        return a;
    }

Andrey Adamovich 2012-02-15

Full version of updated CacheKeySet.java

Tim Eck 2012-02-15

That implementation of toArray() isn’t quite right. You can’t assume the passed in array is the correct size and is supposed to null terminate the array if it is too big.

Also if someone goes to implement this for real I think it is also wrong to get a this.size() and then start to iterate and assume you’ll get the same number of elements from both (in the face of concurrent updates)

Andrey Adamovich 2012-02-16

If array size is bigger than CacheKeySet, then it can be achieved with the following code:

    /**
     * {@inheritDoc}
     */
    public <T> T[] toArray(final T[] a) {
        Iterator<E> iterator = this.iterator();
        for (int i = 0; i < a.length; i++) {
            if (iterator.hasNext()) {
               a[i] = (T) iterator.next();        
            } else {
               a[i] = null;
            } 
        }
        return a;
    }

Tim Eck 2012-02-16

sorry, wasn’t challenging you to fix it :-)

Was just making a note to whoever might go to add an implementation here.

Parameswaran Thangavel 2012-06-18

Hi, I am using ehcache-core-2.5.1.jar and faced above error.

Interestingly, I am getting above error (warning) only when I point my java application to JVM 1.5, if it point it to 1.6 then i am not getting above error.

So, my observation is

For JVM 1.5 “public T[] toArray(final T[] a) " method is invoked and I am getting UnsupportedOperationException but for JVM 1.6 "public Object[] toArray()" method is invoked and it works fine.

Any idea or thought on why the method that get invoked varies as per the JVM version?

    /**
     * {@inheritDoc}
     */
    public Object[] toArray() {
        List<E> list = new ArrayList<E>();
        for (E e : this) {
            list.add(e);
        }
        return list.toArray();
    }

    /**
     * {@inheritDoc}
     */
    public <T> T[] toArray(final T[] a) {
        throw new UnsupportedOperationException();
    }

Tim Eck 2012-06-20

that 1.5 vs. 1.6 behavior is very unusual. I can’t explain that. If you have a test program that demostrates the problem I could get to the bottom of it.

The decision of what method to call (at least by signature) is made at compile time