cancel
Showing results for 
Search instead for 
Did you mean: 

Developing a custom webapp with Alfresco embedded

pitt1
Champ in-the-making
Champ in-the-making
I am writing a proof-of-concept web application that embeds Alfresco and uses its repository services API.  Currently, I'm trying to flush out a few details.

1. I have a simple servlet that grabs the application context and authenticates in the init() method, which will start up the embedded Alfresco instance (modeled after the FirstFoundationClient in the SDK):

ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
AuthenticationService authenticationService = serviceRegistry.getAuthenticationService();
authenticationService.authenticate(username, password.toCharArray());
 

When I visit the servlet in the browser, I sporadically get the following stack trace, which is usually alleviated if I just refresh the page:

09:37:41,994 ERROR [[/AlfrescoAPIServlets-0.1].[EmbeddedAlfrescoServlet]] Servlet.service() for servlet EmbeddedAlfrescoServlet threw exception
net.sf.acegisecurity.AuthenticationCredentialsNotFoundException: A valid SecureContext was not provided in the RequestContext
        at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:477)
        at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:355)
        at net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:77)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:49)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.alfresco.repo.audit.AuditComponentImpl.auditImpl(AuditComponentImpl.java:228)
        at org.alfresco.repo.audit.AuditComponentImpl.audit(AuditComponentImpl.java:166)
        at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:69)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
        at $Proxy14.selectNodes(Unknown Source)

Does anybody have clues as to what the problem could be?

2. The web client uses a different startup method, configured as context listeners defined in web.xml.  This has the effect of starting up the alfresco server when the app server starts up and deploys the application, rather than when the first time the servlet is run.

   <listener>
      <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
   </listener>
  
   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
  
   <listener>
      <listener-class>org.alfresco.web.app.ContextListener</listener-class>
   </listener>

So how do I grab the application context in my servlet once I've started up the embedded Alfresco instance?  If I use the code in #1, it attempts to start the alfresco server all over again.

3. I would like to be able to quickly answer my own questions like the ones above by looking at the Alfresco codebase.  Javadocs are helpful when writing client code, but they don't really explain the package hierarchy.  Is anyone aware of documentation that describes this?  For example, I'd like to know where to look to find out how web service calls translate to repository api calls on the server side. There's only so much I can infer from looking at package names.  Smiley Happy
3 REPLIES 3

pmonks
Star Contributor
Star Contributor
Regarding #2, if the application context is already loaded via a Spring WebApplicationContext (which is how the web client does things), you can use the following code to obtain a reference to it (and from there a reference to the service registry):

    ApplicationContext ctx = (ApplicationContext)request.getSession().getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    ServiceRegistry    reg = (ServiceRegistry)ctx.getBean("ServiceRegistry");

A minor simplification is to implement the ServletContextAware interface in your servlets and/or filters, and then follow the same steps above.  I've not tried this myself yet.

pitt1
Champ in-the-making
Champ in-the-making
Thanks for the tip!  I have found that the web client does this slightly differently, using a spring method to grab the web application context:


WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
ServiceRegistry serviceRegistry = (ServiceRegistry) wc.getBean(ServiceRegistry.SERVICE_REGISTRY);

pmonks
Star Contributor
Star Contributor
Nice!  I didn't know that that Spring API existed!  😉