PooledSession not visible from class loader.

102 views
Skip to first unread message

Joost Oudeman

unread,
Jun 2, 2015, 4:25:42 AM6/2/15
to hippo-c...@googlegroups.com
Hey all,

I'm adding a custom jcr event listener through Spring configuration, using Hippo 7.9.7


Not I'm in need of a Session here, so I figured to use the defaults provided.
All goes well, but when I try to get the session, it gives me an error making no sense to me.
The line: Session sessie = repository.login(credentials);

Can someone help out on this?

My configuration looks like this:

site\src\main\resources\META-INF\hst-assembly\overrides\myListener.xml

  <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="jcrObservationEventListenerItems" />
    <property name="targetMethod" value="add" />
    <property name="arguments">
      <bean class="org.hippoecm.hst.core.jcr.EventListenerItemImpl">
                  <property name="noLocal" value="false" />
        <property name="nodeAddedEnabled" value="false" />
        <property name="nodeRemovedEnabled" value="false" />
        <property name="propertyAddedEnabled" value="false" />
        <property name="propertyChangedEnabled" value="true" />
        <property name="propertyRemovedEnabled" value="false" />
        <property name="absolutePath" value="/content/documents/portal" />
        <property name="deep" value="true" />
        <property name="eventListener">
          <bean class="nl.myhipposite.listener.portal.PortalDocumentListener">
            <property name="credentials" ref="javax.jcr.Credentials.default" />
            <property name="repository" ref="javax.jcr.Repository" />
            <property name="mailFrom" value="${portal.mail.from}"/>
            <property name="mailPath" value="${portal.mail.template.path}"/>
          </bean>
        </property>
      </bean>
    </property>
  </bean>



ERROR:

02.06.2015 10:09:58 ERROR [nl.myhipposite.listener.portal.PortalDocumentListener.onPropertyChanged():85] Er was een probleem bij het ophalen van gegevens
javax.jcr.RepositoryException: javax.jcr.LoginException: Failed to borrow session from the pool. java.lang.IllegalArgumentException: interface org.hippoecm.hst.core.jcr.pool.PooledSession is not visible from class loader
    at org.hippoecm.hst.core.jcr.pool.LazyMultipleRepositoryImpl.login(LazyMultipleRepositoryImpl.java:200)
    at org.hippoecm.hst.core.jcr.pool.MultipleRepositoryImpl.login(MultipleRepositoryImpl.java:172)
    at nl.myhipposite.listener.portal.PortalDocumentListener.getSession(PublishMatchReviewDocumentListener.java:201)
    at nl.myhipposite.listener.portal.PortalDocumentListener.getNode(PublishMatchReviewDocumentListener.java:192)
    at nl.myhipposite.listener.portal.PortalDocumentListener.isValid(PublishMatchReviewDocumentListener.java:178)
    at nl.myhipposite.listener.portal.PortalDocumentListener.onPropertyChanged(PublishMatchReviewDocumentListener.java:79)
    at org.hippoecm.hst.core.jcr.GenericEventListener.onEvent(GenericEventListener.java:112)
    at org.apache.jackrabbit.core.observation.EventConsumer.consumeEvents(EventConsumer.java:249)
    at org.apache.jackrabbit.core.observation.ObservationDispatcher.run(ObservationDispatcher.java:161)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.jcr.LoginException: Failed to borrow session from the pool. java.lang.IllegalArgumentException: interface org.hippoecm.hst.core.jcr.pool.PooledSession is not visible from class loader
    at org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository.login(BasicPoolingRepository.java:339)
    at org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository.login(BasicPoolingRepository.java:354)
    at org.hippoecm.hst.core.jcr.pool.LazyMultipleRepositoryImpl.login(LazyMultipleRepositoryImpl.java:182)
    ... 9 more
Caused by: java.lang.IllegalArgumentException: interface org.hippoecm.hst.core.jcr.pool.PooledSession is not visible from class loader
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:616)
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:592)
    at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:244)
    at java.lang.reflect.WeakCache.get(WeakCache.java:141)
    at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:455)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:738)
    at org.hippoecm.hst.core.jcr.pool.util.ProxyFactory.createInterceptorProxy(ProxyFactory.java:51)
    at org.hippoecm.hst.core.jcr.pool.PooledSessionDecoratorProxyFactoryImpl.decorate(PooledSessionDecoratorProxyFactoryImpl.java:44)
    at org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository$SessionFactory.makeObject(BasicPoolingRepository.java:1109)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148)
    at org.hippoecm.hst.core.jcr.pool.BasicPoolingRepository.login(BasicPoolingRepository.java:326)
    ... 11 more

Ard Schrijvers

unread,
Jun 2, 2015, 7:19:32 AM6/2/15
to hippo-c...@googlegroups.com
Hey Joost,

this was a hard nut to crack. Seems related to ProxyFactory combined
with JCR events being dispatched from the CMS webapp classloader. A
workaround is quite simple (see below). I will fix it in the HST in
[1].

Apart from this, some small remarks:

instead of

<property name="targetObject" ref="jcrObservationEventListenerItems" />
<property name="targetMethod" value="add" />

you can better use 'customJcrObservationEventListenerItems' in your
end project, see [2].

Also make sure that if you access a jcr session in a listener, that
you make sure to logout the session at the end. Namely, even though
you get a pooled HST session, there is not resource management because
you are not in context of a hst request. Hence, you need in a finally
to logout the jcr session.

Last thing: The HST and in general listeners typically do not have
this problem you describe because they are only used to register
events, say, in some queue. Then, another consumer acts on this queue.
The advantage is that jcr event listening can better not take too long

HTH, Regards Ard

Temporary solution for you:

@Override
public void onEvent(EventIterator events) {
final ClassLoader currentCL =
Thread.currentThread().getContextClassLoader();
Session session = null;
try {
Thread.currentThread().setContextClassLoader(DocListener.class.getClassLoader());
session = repository.login(credentials);

while (events.hasNext()) {
if (eventIgnorable(events.nextEvent())) {
continue;
}
return;
}
} catch (RepositoryException e) {
// log
} finally {
if (session != null) {
session.logout();
}
Thread.currentThread().setContextClassLoader(currentCL);
}
}


[1] https://issues.onehippo.com/browse/HSTTWO-3323
[2] http://www.onehippo.org/library/concepts/hst-spring/how-to-add-custom-jcr-event-listener-through-spring-configuration.html
> --
> Hippo Community Group: The place for all discussions and announcements about
> Hippo CMS (and HST, repository etc. etc.)
>
> To post to this group, send email to hippo-c...@googlegroups.com
> RSS:
> https://groups.google.com/group/hippo-community/feed/rss_v2_0_msgs.xml?num=50
> ---
> You received this message because you are subscribed to the Google Groups
> "Hippo Community" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to hippo-communi...@googlegroups.com.
> Visit this group at http://groups.google.com/group/hippo-community.
> For more options, visit https://groups.google.com/d/optout.



--
Hippo Netherlands, Oosteinde 11, 1017 WT Amsterdam, Netherlands
Hippo USA, Inc.- 745 Atlantic Ave, Eight Floor, Boston MA 02111,
United states of America.

US +1 877 414 4776 (toll free)
Europe +31(0)20 522 4466
www.onehippo.com

Woonsan Ko

unread,
Jun 2, 2015, 7:38:03 AM6/2/15
to hippo-c...@googlegroups.com

Hi,

Let me ask some questions.
Do you have multiple HST web applications?
Are you running on tomcat7 or 8?
Can you search hst-api jar file (s) under tomcat?

Woonsan
(Sent via my mobile device. Apologies for any typos.)
   

--

Joost Oudeman

unread,
Jun 2, 2015, 8:32:08 AM6/2/15
to hippo-c...@googlegroups.com
@Ard: thanks for the workaround. I'll give it a go.
As for the approach of putting it in a queue and use other consumers. Is there some example in the documentation you can suggest?


@Woonsan: I am running a local cargo.run. It uses tomcat 7 as provided by Hippo. I guess that means I have the site and cms as hst applications running.
A search gave me this result:

$ find target -name "hst-api*.jar"
target/tomcat7x/webapps/cms/WEB-INF/lib/hst-api-2.28.09.jar
target/tomcat7x/webapps/site/WEB-INF/lib/hst-api-2.28.09.jar


Hope this helps.

Ard Schrijvers

unread,
Jun 2, 2015, 8:42:17 AM6/2/15
to hippo-c...@googlegroups.com
On Tue, Jun 2, 2015 at 2:32 PM, Joost Oudeman <oude...@gmail.com> wrote:
> @Ard: thanks for the workaround. I'll give it a go.

the workaround will work. I am providing the solution now by default
to hst trunk to make sure always the correct classloader is used

> As for the approach of putting it in a queue and use other consumers. Is
> there some example in the documentation you can suggest?

Just create two spring beans, one is the listener that writes the
event paths to a queue, another spring bean that monitors the queue
and acts when it is not empty. You could even just do it in a single
bean, consume all events and write them in some list/queue/stack and
have that one processed by a executor using a different thread (so the
onEvent methods ends really fast)

Note that I almost fixed
https://issues.onehippo.com/browse/HSTTWO-3323 in trunk

Regards Ard

Joost Oudeman

unread,
Jun 2, 2015, 10:48:24 AM6/2/15
to hippo-c...@googlegroups.com
Well, I got it working with a separate service, it works now.

However I'm a bit curious what the advantage is to use the customJcrObservationEventListenerItems instead of the configuration I have..
Any explanations for why to override the bean?

Ard Schrijvers

unread,
Jun 3, 2015, 4:39:13 AM6/3/15
to hippo-c...@googlegroups.com
On Tue, Jun 2, 2015 at 4:48 PM, Joost Oudeman <oude...@gmail.com> wrote:
> Well, I got it working with a separate service, it works now.

Great! Note I also already fixed
https://issues.onehippo.com/browse/HSTTWO-3323 because the way you
used it should not result in the problem you saw.

>
> However I'm a bit curious what the advantage is to use the
> customJcrObservationEventListenerItems instead of the configuration I have..
> Any explanations for why to override the bean?

The end result is pretty much the same. In the HST we have an empty
'customJcrObservationEventListenerItems' which can be overridden by
end projects to inject custom listeners.

Guess it is a bit a matter of taste. I personally try to have end
users avoid having to use MethodInvokingFactoryBean. If at some point
we decide that jcrObservationEventListenerItems in the HST core gets
changed to a Map, your 'add' method will fail. For
'customJcrObservationEventListenerItems' we know it is meant for end
users and would never change it without deprecating.

At the same time, we are a bit on thin ice: The spring component beans
are part of hst core (so no compile dependency against) but at the
same time, developers need to use the bean ids to for example extend
behavior. It would be cleanest if we could split the spring
configuration in a core part and 'api' part that can be used by end
projects.

So in a nutshell, in practice it doesn't really matter that much,
certainly not for now

Regards Ard
Reply all
Reply to author
Forward
0 new messages