cancel
Showing results for 
Search instead for 
Did you mean: 

Load class file from shared/lib with alfresco dependency

loftux
Star Contributor
Star Contributor
Is there a way for a custom class to be placed in shared/lib and still load dependencies in WEB-INF/lib?

Background
I was trying to move away from amp file distribution to all jar for alfresco addons. This works well for all non java stuff, but for my jar with a custom java class extending/dependent on alfresco classes it only loads when placed in WEB-INF/lib. I would like to place it in shared/lib, in that way it will be kept between alfresco.war redeploys.

What I have tested
I have a bean loading from
shared/classes/alfresco/module/loftux/context/service-context.xml
<bean id="loftuxutilsScript" parent="baseJavaScriptExtension" class="se.loftux.repo.jscript.LoftuxScriptUtils">
        <property name="extensionName">
            <value>loftuxutils</value>
        </property>
        <property name="serviceRegistry">
            <ref bean="ServiceRegistry"/>
        </property>
    </bean>
My jar is loftux.alfresco.jar.
The class is a simple extension in java to add utility functions to javascript. It therefor is dependent on bean baseJavaScriptExtension. That bean is found in one of the jars in WEB-INF/lib.

If I place my jar in WEB-INF/lib it loads just fine. If placed in any other lib directory it fails with (only part of the error pasted)
09:35:49,373 ERROR [org.springframework.web.context.ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'LuceneFullTextSearchIndexer' defined in class path resource [alfresco/core-services-context.xml]: Cannot resolve reference to bean 'luceneFullTextSearchIndexer' while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'luceneFullTextSearchIndexer' defined in class path resource [alfresco/core-services-context.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [se.loftux.repo.jscript.LoftuxScriptUtils] for bean with name 'loftuxutilsScript' defined in URL [file:/opt/alfresco/loftux/tomcat/shared/classes/alfresco/module/loftux/context/service-context.xml]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/alfresco/repo/jscript/BaseScopableProcessorExtension
i.e it cannot find a class file needed.
So from what I can tell from reading http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html classes in WEB-INF/lib can read from lib folders higher in the hiearchy, but the other way around (the way I want to) isn't possible.

Or is there a way with som spring bean config magic, or tomcat class loading config?
7 REPLIES 7

afaust
Legendary Innovator
Legendary Innovator
Hello,

I am afraid what you want is not easily achievable and should never be. You may achieve something in this manner by seriously hacking the ClassLoading mechanisms (e.g. by providing a custom ClassLoader yourself). This can only be done at the Tomcat / Java level - Spring itself can not overcome constraints imposed by ClassLoading.

shared/lib should always only contain JARs without dependencies to a specific web application to be used as a dependency by any of the deployed web applications. What if you have deployed two web applications with the same class of potentially different versions - which class should be used as the parent class?
shared/classes is essentially the same, which is why we are thinking of actually moving bean configuration files into a configuration AMP and externalizing properties (e.g. alfresco-global.properties) to a JNDI directory.

As for deployment of alfresco.war removing the JAR when placed in WEB-INF/lib - we source control the original alfresco.war and integrate our artifacts (AMP, JAR and the works) within our build process, so that when we re-deploy the built alfresco.war, the state is the same as before. Since we also source control dev environment configurations, re-deployment also retains any configuration customization made in the deployed / exploded WAR as long as developers stick to the routine of checking in their configuration. The only time local changes are actually sensible is for short roundtrip fix + test (when the developer is sure of what he is doing) or trial + error (deprecated) cycles without build system overheads. And with a proper incremental build system and suitable local hardware, these overheads should become un-noticable.

Regards
Axel Faust

loftux
Star Contributor
Star Contributor
Thanks for your reply,
I've done all amps deployment, merging my customizations into a the war file. Since some class files do have to (as you are explaining) have to be part of the WEB-INF/lib and hence the war file, it does not help you much to first put your non java stuff in a jar, then amp merge it into the war.

The jar only deployment stuff does however work well when you want to distribute small addons without java class files, like the share-extras.

afaust
Legendary Innovator
Legendary Innovator
Hello,

sure, the non-Java JAR-only deployment works for small addons - but this doesn't necessarily mean it is clean from a class loading / enterprise architecture perspective in terms of separation of applications. For example, Share as a small-footprint application would allow for parallel deployment of different versions / specialisations into the same Tomcat instance - now, if you deploy any addon in /shared/lib it will be picked up by all Share instances indiscriminately, which you might not want (same goes for web-extension).

The great thing about discussions in this area is, that it basically comes down to what you are allowed to do in the target environment and what your personal / organisation preferences are. As we are an all-round consulting company, we have certain processes that have to work together for development, maintenance and operations management. One of these processes - standard for all applications we develop/support/operate on customers behalf - requires that deployment of a web application into test / production only relates to a single artifact (WAR / EAR) and environment specific configuration has to be picked up from a manageable, central source (JNDI).

Regards
Axel

mrinal3199
Champ in-the-making
Champ in-the-making
Hi,

  I am also getting the same error as "No bean found" and Context Initialization failed while starting the alfresco server. I want to create a new custom evaluator so that i can keep an action only on some specific folders depending on their names. E.g: say i have created an action in share config file as "Bulk Export". Now, i want it only to be shown on some of the folders named as "A" or "B" or "C". Please help me with this.

Thanks..

mrinal3199
Champ in-the-making
Champ in-the-making
Hello,

   I have created an evaluator in my share jar in the package "org.alfresco.web.evaluator.doclib.action" named as NameEqualsEvaluator.java. And in the share cnfig i have defined an action for the folders and evaluator id is given as "evaluator.doclib.action.isInstanceType". So, in Custom-slinshot-applicaton.xml, i have defined this id with parent as "org.alfresco.web.evaluator.doclib.action.NameEqualsEvaluator". I build this jar and laced it in "C:\alfresco\tomcat\webapps\share\WEB-INF\lib". I also have another utils jar which  am keeping in "C:\alfresco\tomcat\webapps\alfresco\WEB-INF\lib". The problem is while starting the server, it is giving errr as:

org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'evaluator.doclib.action.isInstanceType' defined in URL [jar:file:/C:/Alfresco/tomcat/webapps/share/WEB-INF/lib/SkandiaShare.jar!/alfresco/web-extension/custom-slingshot-application-context.xml]: Could not resolve parent bean definition 'org.alfresco.web.evaluator.doclib.action.NameEqualsEvaluator'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.alfresco.web.evaluator.doclib.action.NameEqualsEvaluator' is defined

I am not getting why this class is not being loaded but every webscripts which i have in utils jar are working fine.

Please suggest me how to reslve this issue.

Thanks in advance

sangeetha
Champ in-the-making
Champ in-the-making
If i added alfresco addons jar file into the tomcat/shared/lib and then restating tomcat started and stopped immediately. After i removed that i can run the tomcat service. Need a clarification.

What addOn did you add? What's in the logs?