cancel
Showing results for 
Search instead for 
Did you mean: 

Getting application context in Java backed Web script

nilsw
Champ in-the-making
Champ in-the-making
What is the best way to access the Spring application context in a Java backed web script? I want to use it to load a classpath resource (an XSL file). I have tried ApplicationContextHelper.getApplicationContext(), which tries to load the application context where the web script in question is declared, but gets an error:

20:53:38,217 User:admin ERROR [scripts.export.OrderPrint] Could not create a print order
org.springframework.beans.factory.BeanDefinitionStoreException: Error registering bean with name 'webscript.com.cadq.alfresco.common.repository.export.stream-temp-file' defined in file [C:\Users\nils.weinander\Program\Alfresco-3.1\tomcat\shared\classes\alfresco\extension\cadq-projektnavet-alfresco-context.xml]: Could not resolve parent bean definition 'webscript'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'webscript' is defined
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'webscript' is defined

cadq-projektnavet-alfresco-context.xml refers to webscript:

   <bean id="webscript.com.cadq.alfresco.common.repository.export.stream-temp-file"
         class="com.cadq.alfresco.common.repo.web.scripts.export.StreamTemporaryFile"
         parent="webscript">
      <property name="contentService" ref="ContentService" />
      <property name="mimetypeService" ref="MimetypeService" />
      <property name="nodeService" ref="NodeService" />
      <property name="permissionService" ref="PermissionService" />
   </bean>

is the first bean in it.

I have managed to get an application context by

new ClassPathXmlApplicationContext("alfresco/webscript-framework-application-context.xml")

but creating a new instance doesn't seem right. Is there a way to get a ready instance of a "base" application context from a Java backed web script?
3 REPLIES 3

openpj
Elite Collaborator
Elite Collaborator
ApplicationContextHelper.getApplicationContext() creates a new Alfresco embedded repository reading the repository configuration:

    public synchronized static ConfigurableApplicationContext getApplicationContext(String[] configLocations)
    {
        if (configLocations == null)
        {
            throw new IllegalArgumentException("configLocations argument is mandatory.");
        }
        if (usedConfiguration != null && Arrays.deepEquals(configLocations, usedConfiguration))
        {
            // The configuration was used to create the current context
            return instance;
        }
        // The config has changed so close the current context (if any)
        closeApplicationContext();
       
        instance = new ClassPathXmlApplicationContext(configLocations);
        usedConfiguration = configLocations;
       
        return instance;
    }
An Alfresco repository can be embedded in a JVM only one time, this means that you can't have two Alfresco embedded repository in the same application (same JVM).
All the involved Spring instructions are the following:

instance = new ClassPathXmlApplicationContext(configLocations);
This instruction is a Spring instruction and allows you to create a new Application Context, that's why this solution can't work for your goal.

The solution is based on using the autowire feature of Spring. For each property that you have defined in your custom Spring Bean (your custom Java Backed Web Script), you need to provide a setter method (IoC - setter injection). In this way Spring allows you to set for you all these resources.
For instance, if you need to use the NodeService, you need to provide the following setter method in your Spring Bean implementation:

public NodeService setNodeService(NodeService nodeService){
this.nodeService = nodeService;
}
Then when Alfresco starts for the first time, Spring for you starts to wire all the resources.
Finally you can use all the properties defined in your bean without explictly retrieving these from the Spring Context, you don't need to directly use the Spring Context.

Hope this helps.

nilsw
Champ in-the-making
Champ in-the-making
Unfortunately that doesn't help me. I can set the path of the resource to load in a Spring-defined property, but the Spring resource loading method requires an application context object:

Resource xslt = ctx.getResource(xslFile);

But, if there is no way to access the "current" application context object, it is probably better to use the class loader rather than instantiate an application context, i.e.

InputStream xsltStream = this.getClass().getClassLoader().getResourceAsStream(xslFile);

instead of

ApplicationContext ctx = new ClassPathXmlApplicationContext("alfresco/webscript-framework-application-context.xml");
Resource xslt = ctx.getResource(xslFile);
InputStream xsltStream = xslt.getInputStream();

Unless there is a way to declare the actual resource in my application context and set it as a property for my web script?

nilsw
Champ in-the-making
Champ in-the-making
OK, problem solved through Spring magic  Smiley Happy

If I declare the property as

application-context.xml:
<property name="xslFile" value="classpath:alfresco/extension/printOrder.xsl" />

Java code:
Resource xslFile;

Spring loads the resource for me, et voilà!