Giter VIP home page Giter VIP logo

xenit-eu / dynamic-extensions-for-alfresco Goto Github PK

View Code? Open in Web Editor NEW
77.0 25.0 31.0 32.78 MB

Rapid development of Alfresco repository extensions in Java. Deploy your code in seconds, not minutes. Life is too short for endless server restarts.

License: Apache License 2.0

Java 95.64% JavaScript 0.37% CSS 0.20% Groovy 1.18% FreeMarker 2.61%
alfresco alfresco-module alfresco-addon alfresco-development product

dynamic-extensions-for-alfresco's Introduction

Dynamic Extensions for Alfresco

Apache License 2 CI Maven Central

Xenit Logo

Dynamic Extensions is a part of the Xenit Open Source Tooling around Alfresco. Xenit is company with a deep expertise and a strong team around Alfresco. If you'd like to learn more about our tools, services and products, please visit our website.

Add OSGi based hot-deploy functionality and Spring annotation based configuration to Alfresco.

Introduction

Rapid development of Alfresco repository extensions in Java. Deploy your code in seconds, not minutes. Life is too short for endless server restarts.

Dynamic Extensions adds an OSGi container to the Alfresco repository, enabling live deployment of Java code, with no need to restart the server. Alfresco itself is not "OSGi-fied" in any way; the OSGi container runs on top of the core Alfresco platform.

Standard Alfresco Platform Extensions use Spring XML based configuration. With Dynamic Extensions, developers have the ability to create Alfresco Platform Extensions using Spring's annotations based configuration.

Installing Dynamic Extensions in Alfresco

Dynamic Extensions (DE) is distributed as an Alfresco Module Package (AMP) extension that can be installed in Alfresco.

Installing the Dynamic Extensions AMP

To support multiple Alfresco versions, different AMPs for each minor Alfresco version update are build and distributed.
E.g. if you are working with Alfresco 6.0.7-ga, you should use the alfresco-dynamic-extensions-repo-60 artifact.

Maven Central Coordinates

All required artifacts, including the AMP to be installed in Alfresco, are available in Maven Central.

<dependency>
    <groupId>eu.xenit</groupId>
    <artifactId>alfresco-dynamic-extensions-repo-${alfresco-version}</artifactId>
    <version>${latest-dynamic-extensions-version}</version>
    <type>amp</type>
</dependency>
alfrescoAmp "eu.xenit:alfresco-dynamic-extensions-repo-${alfrescoVersion}:${dynamicExtensionsVersion}@amp"

These artifacts can be used to automatically install Dynamic Extensions in Alfresco using e.g. the Alfresco Maven SDK or the Alfresco Docker Gradle Plugins

Manual download and install

Supported Alfresco versions

Dynamic Extensions is systematically integration-tested against:

  • Alfresco Enterprise & Community 7.4
  • Alfresco Enterprise & Community 7.3
  • Alfresco Enterprise & Community 7.2
  • Alfresco Enterprise & Community 7.1
  • Alfresco Enterprise & Community 7.0
  • Alfresco Enterprise & Community 6.2 (Requires hotfix, see below)
  • Alfresco Enterprise & Community 6.1 (Requires hotfix, see below)

Integration tests are currently only executed on our private Jenkins build server.

Known Alfresco issues that impact Dynamic Extensions

Alfresco 6.1 / 6.2 - wrong version of 'Commons annotations' usedWhen using DE on Alfresco 6.1 or 6.2, it is possible that it fails to startup due to following error:
Caused by: java.lang.NoSuchMethodError: javax.annotation.Resource.lookup()Ljava/lang/String;
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.<init>(CommonAnnotationBeanPostProcessor.java:621)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.lambda$buildResourceMetadata$0(CommonAnnotationBeanPostProcessor.java:383)
at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:719)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:365)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:350)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:298)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1044)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:550)

The root cause is for this problem is that Alfresco has multiple implementations of the JSR 250 specification, 'Common Annotations' in the WEB-INF/lib/ folder:

  1. javax.annotation:javax.annotation-api
  2. javax.annotation:jsr250-api
  3. org.apache.geronimo.specs:geronimo-annotation_1.0_spec

Only the first one is up to date and contains the correct implementation of the Resource class. The other two versions contain an old implementation of the Resource class, causing the provided error to be thrown by Spring internally.

This is only an issue as of Java 11 (Alfresco 6.1) because earlier versions had an correct implementation of the Resource class embedded in the distribution, and the bootstrap classloader has the highest priority.

This issue has been reported to Alfresco: MNT-20557. Waiting for Alfresco to fix the issue, following workarounds can be used to make DE work on Alfresco 6.1 and 6.2:

  • Remove the jsr250-api and geronimo-annotation_1.0_spec jars from the WEB-INF/lib folder of the Alfresco webapp.
  • Install this hotfix AMP in your Alfresco distribution, which will overwrite the jsr250-api and geronimo-annotation_1.0_spec jars with empty jars.

Example Dynamic Extensions based Alfresco Platform extension

This example Web Script examines a node and passes information to a Freemarker template:

@Component
@WebScript
public ExampleWebScript {

  @Autowired
  private NodeService nodeService;

  @Uri("/show-node")
  // Example: http://localhost/alfresco/service/show-node?nodeRef=workspace://SpacesStore/12345
  public Map<String, Object> displayNodeName(@RequestParam NodeRef nodeRef) {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("properties", nodeService.getProperties(nodeRef));    
    return model; // Model is passed to Freemarker template.
  }
}

Note that this is an annotation Web Script. These types of Web Script are configured through Java annotations instead of *.desc.xml descriptors. Annotation Web Scripts are similar to Spring MVC's annotation-based controllers.

Here's the accompanying Freemarker template fragment:

<table>
  <#list properties?keys as name>    
    <tr>
      <th>${name}</th>
      <td>${properties[name]!''}</td>
    </tr>
  </#list>
</table>

This is all the code that is required; there's no need for Spring XML config or Web Script XML descriptors. Hot-reloading and reducing configuration overhead are not particularly novel concepts in the Java development world at large. Essentially, Dynamic Extensions modernizes the development of Alfresco repository extensions.

The example above may be trivial, but the point is that, behind the scenes, services are still wired together through Spring and handled by the Web Script framework. Conceptually there is no real difference between a Dynamic Extension and a regular Alfresco extension. There's just less overhead and more convenience.

Documentation

Please checkout the documentation for further instructions.

License

This project is licensed under the Apache V2 License - see the LICENSE file for details.

Useful links

dynamic-extensions-for-alfresco's People

Contributors

al-sabr avatar evyrosseels avatar hechmi-dammak-xenit avatar jasper-hilven avatar jaspervdb avatar jonasheylen avatar kerkhofsd avatar kpiot123 avatar laurens-runnable avatar laurentvdl avatar martinbaptiste avatar qwiff-dogg avatar rschev avatar rvanhuyssexenit avatar stanmine avatar tgeens avatar thijslemmens avatar todorinskiz avatar tom-vandepoele avatar vdewillem avatar vierbergenlars avatar yregaieg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dynamic-extensions-for-alfresco's Issues

Move alfresco-api-util to a separate Github project

The alfresco-api-util library is a remnant from the previous Google Code projects.

The model registration logic is the only part of the library that has added value for Dynamic Extensions. This logic will be moved to alfresco-integration.

The rest of the library is still useful for general use within Alfresco extensions and will be spun off into a separate Github project.

Post 1.0

Future enhancements after 1.0 release.

Web Script handler interceptor methods

Add Web Script annotations that provide interceptor logic similar to
a Spring MVC HandlerInterceptor. This lets you extract common request handling logic into superclasses.

These methods should accept the same arguments as @Attribute and @Uri-annotated methods. They can return booleans to control the request handling flow.

@Inject
private NodeService nodeService;

@Before
public boolean checkIfNodeExists(@RequestParam NodeRef nodeRef, WebScriptResponse response) {
  if (nodeService.exists(nodeRef)) {    
    return true; // Proceed.
  } else {
    response.setStatus(404);    
    return false; // End request handling.
  }
}

Migrate from Maven to Gradle

The project will move to Gradle. Hands-on experience shows that Gradle is a good substitute for Maven. Gradle does, however, lack proper support for provided dependencies, but one can work around this. See: http://issues.gradle.org/browse/GRADLE-784

Generating the AMP will be done manually. After all, an AMP is simply a ZIP file. (There is a Gradle plugin for generating AMPs, https://github.com/AlfrescoLabs/alfresco-gradle-plugins, but it does not seem to be actively maintained.)

Implement proper application management

The OSGi bundle lifecycle is unsuitable for integrating proper application management. The problem is that the OSGi lifecycle is invoked every time the Alfresco repository - and with it, the OSGi container - is started and stopped.

In short: OSGi does not seem to provide a way of indicating that a bundle is installed for the first time or uninstalled permanently. (TODO: Verify if this is true.)

Dynamic Extensions should provide entry points for initially setting up and permanently uninstalling an extension. These entry points can then be invoked through the Dynamic Extensions console. These entry points will most likely be defined through Java annotations.

Improve logging

Logging is not handled consequentially through the codebase. Some of the more complex parts of the code do not log any activity at all, making troubleshooting and error diagnosis during production scenarios harder than it should be.

Standard CSS and JavaScript resource endpoints

Currently, there is no way for a Dynamic Extension to link to its own JavaScript and CSS resources from Freemarker HTML templates.

The workaround is to <#include> the CSS and JavaScript inline.

One solution would be to add a Freemarker directive that generates <link> and <script> tags by scanning the bundle for resources.

Example:

Given a screen.css file in the META-INF folder of the bundle, the following Freemarker directive:

<#styles/>

would result in this HTML:

<link href="/alfresco/service/dynamic-extensions/css/[bundle name]/screen" type="text/css" />
<!-- 
Note the lack of the  `.css` extension in the URL. 
Web Scripts use the filename extension to map the output content type,
which is not what we want.
-->

Dynamic Extensions should then provide a standard Web Script for handling the dynamic-extensions/css endpoint.

Support for Spring @Configuration

Investigate configuring application contexts through Java classes, both for Dynamic Extensions itself as for OSGi bundles.

The support for @Configuration in Spring 3.0 is somewhat limited (Spring 3.1 expanded on this) but it is still useful.

Basic support for @Configuration seems to work, now that CGLIB classloading issues are resolved.

Dynamic Extensions console

The console is a (client-side) JavaScript application for managing extensions.

  • Add JSON API for retrieving info on bundles in the OSGi Framework.
  • Add JSON API to control bundle lifecycle (start, stop, install, uninstall)
  • Create Ember UI for managing bundles.

OSGi configuration using XML

The current OSGi service and system package configuration use text files containing a colon-delimited list. While this format will continue to be supported, configuring OSGi services should also be possible using XML.

Using XML allows, for example, for easy transformation to a more readable format using XSLT.

Example service config: https://github.com/lfridael/dynamic-extensions-for-alfresco/blob/master/alfresco-integration/src/main/resources/META-INF/spring/osgi-container/services/alfresco-public-services.txt

JavaScript and CSS resource delivery framework

Experience with creating the Data Dictionary browser revealed the need for improving the organization of scripting code. A JavaScript and CSS resource delivery framework would be a great help.

Such a framework speeds up development of JavaScript-based "console" applications for managing extension configuration. These applications ensure that everything is kept in the Alfresco repository and thus obviates the need for extending Alfresco Share. (Which can be time-consuming.) The Data Dictionary browser is just a relatively simple example of such a JavaScript application. More advanced use cases are in the pipeline.

Summary:

  • Extensions contain CoffeeScript/JavaScript and CSS resource in predefined locations. (see below)
  • Dynamic Extensions detects the presence of these resources (in a bundle) and instantiates a Web Script for serving these resources.
  • The Web Script automatically compiles, concatenates and compresses the resources.
  • Compile CoffeeScript.
  • Compile LESS stylesheets.

Example resource structure:

/META-INF/web/scripts/console.coffee.js
/META-INF/web/stylesheets/screen.less.css

Use the Data Dictionary browser as a pilot project for this framework.

Support for new Alfresco multi-tenancy implementation

Future Alfresco releases will contain changes to the multi-tenancy implementation that breaks the integration with annotation-based Web Scripts.

These breaking changes might come with the release of Alfresco 4.2 already.

Override Webscript behaviour

@lfridael I used an AnnotationBasedWebScriptHandler override to add certain template variables to all my templates (Bnd-LastModified for caching & alf_ticket).

With the new Webscript handling, this logic has moved to AnnotationWebScript instances.
So to override, I would have to also override AnnotationWebScriptBuilder.createWebScript to return a custom type.

Should I just refactor (inside d extensions) the instantiation of the AnnotationWebscript instance to a separate protected method or am I missing something?

Limitations for OSGI bundles installed through the filesystem

Dynamic Extensions uses the following types of bundles:

  • Framework bundles: the Dynamic Extensions framework itself. These bundles are placed in the Alfresco repository application through deployment of the Dynamic Extensions AMP.
  • Repository bundles: stored at /Data Dictionary/Dynamic Extensions/Bundles
  • Classpath bundles: located in the classpath folder /dynamic-extensions/bundles

    In a typical Alfresco installation this corresponds to <alfresco>/tomcat/shared/classes/dynamic-extensions/bundles.

The OSGI container coordinates the installation and startup of the above types of bundle on startup. For example, the implementation avoids starting up bundles that have missing dependencies. As an aside: missing bundle dependencies should not occur in production environments, as this would then need manual intervention to get the repository (as a whole) up-and-running.

Additionally, Dynamic Extensions supports:

  • Filesystem bundles: managed by the Apache Felix FileInstall plugin. FileInstall monitors a given directory for bundle JARs.

The important thing to note is that FileInstall installs bundles asynchronously. This becomes an issue when Repository or Classpath bundles depend on Filesystem bundles. In this case Dynamic Extensions cannot guarantee the order of bundle installation and the startup of dependent bundles usually fails. You can fix this manually by starting the bundles through the Contol Panel afterwards, but this is obviously not the way to handle this in production environments.

The takeaway: to guarantee correct repository startup, Repository and Classpath bundles can depend on each other, but not on Filesystem bundles, and vice versa.

Status page

The old Dynamic Extensions console has been removed from the codebase and will be replaced with a simpified status page that shows information on the available extensions.

Handling time zones when displaying bundle modification dates

The current implementation does not use a time zone for parsing bundle modification dates. This leads to errors when viewing the Control Panel in a client time zone that is different from the server time zone.

The solution would be to output the modification date with time zone information in a format that can be parsed by the moment.js library.

Control Panel, annotation-based Web Scripts index

As explained in the notes for #49 annotation-based Web Scripts do not show up in the repository Web Script index. As an alternative, the Control Panel should show its own index for annotation-based Web Scripts.

@Header annotation

Annotation-based Web Scripts should have a @Header annotation to map HTTP headers
to handler method arguments

public void handleResource(@Header("If-None-Match") String eTag)

OSGi configuration using files in the Alfresco repository

OSGi service and system package configuration is currently loaded from the classpath. With the (upcoming) ability to restart the OSGi container, there should also be a way to load this configuration from files in the repository.

Alfresco service interface requirement

Currently, the ServiceBundleContextRegistrar verifies that exported Alfresco services implement an interface.

Can this requirement be dropped ?

(the typical OSGI use-case of swapping in/out service implementations at runtime does not seem to apply here)

Change bean definition scanning

When no Spring XML configuration is present, the implementation currently uses the Export-Package header to discover Java packages to scan for Spring bean definitions. This turns out to be an anti-pattern, as bean definition scanning is an implementation detail and should not be tied to the concepts of OSGi export, import or private packages.

To address this, the implementation will use a dedicated bundle header Alfresco-Spring-Configuration, containing a comma-delimited list of Java packages to scan.

Support for Export-Package will be removed in milestone 6.

Recap: to mark an OSGi bundle as a Dynamic Extension, it must have this header:

Alfresco-Dynamic-Extension: true

If you're using Spring XML configuration, the above is all you need to get a Dynamic Extension. The framework scans for XML files in /META-INF/spring.

To get an Dynamic Extension running without Spring XML config, the bundle must have this additional header:

Alfresco-Spring-Configuration: nl.runnable.backstage,nl.runnable.other.package

Without this header, the bundle will be loaded, but no beans will get instantiated and the implementation logs a warning about this.

As an aside: without the Alfresco-Dynamic-Extension header, the implementation treats bundles as regular Spring Dynamic Modules. Using regular Spring DM bundles is technically a viable option, but not a future-proof approach, as Spring has moved away from OSGi.

System Package cache configuration

To address potential classpath issues during startup, there should be a configuration option to control how the OSGi container uses the system package cache.

# Use existing cache or create a new cache if none exists. Default setting.
osgi.container.system-package-cache = ENABLE
# Force update of the existing cache.
osgi.container.system-package-cache = UPDATE
# Disable the cache.
osgi.container.system-package-cache = DISABLE

Maven plugin for creating standalone AMPs

Maven plugin that generates a standalone AMP from existing Dynamic Extension Maven projects. This maintains existing Alfresco application management practices (i.e. the AMP approach), while keeping the rapid development of Dynamic Extensions.

It should be possible to install multiple of such Dynamic Extension AMPs side-by-side. This requires more refactorings of the codebase. The idea is to move all Alfresco integration code into OSGi bundles. The only duplicate dependency should be the Felix OSGi framework.

The vault-amp project prototypes the creation of standalone AMPs. Its pom.xml is far too complex, however.

Improve test coverage

The code project needs better test coverage for future regression testing.

In practice this means more unit tests for annotation-runtime and alfresco-integration and OSGi integration tests for blueprint-integration.

Target: 75% code coverage.

Reinstate repository bundle management

Repository bundle management (i.e. managing OSGi bundles through the repository Data Dictionary) was deprecated earlier.

Related code should be undeprecated and cleaned up.

Make @WebScript annotation optional

Milestone 6 will introduce changes in annotation Web Script detection that makes @WebScript optional.

Groovy example:

@Component
class Bundles {
  @Uri('/bundles/{id}')
  def show(@UriVariable String id) { /* Implementation */ }
}

The new implementation will scan every available bean for @Uri annotated methods.

Refactor annotation-based Web Scripts implementation

The implementation of annotation-based Web Scripts is due for a major refactoring, as the current code (2 years old) has become too hard to maintain.

With the Web Script test cases now in place, the implementation can be refactored much more easily.

Make OSGi container a subsystem

The current implementation uses a module component to bootstrap the OSGi container . It is worth investigating whether bootstrapping the OSGi container as an Alfresco subsystem instead has significant advantages.

http://wiki.alfresco.com/wiki/Alfresco_Subsystems

Conceptually, the OSGi container is already very similar to a subsystem: both use a child application context, with the advantage being that this child context can be restarted at runtime.

Control Panel, filtering bundles by category

To make the display of large numbers of bundles a bit more user-friendly, the Control Panel should allow for grouping/filtering bundles by category.

The categories should be specified through a bundle header.

Examples:

Alfresco-Extension-Categories: library,utility
Alfresco-Extension-Categories: interface
Alfresco-Extension-Categories: rest-api

Extension installation history

The OSGi container should maintain a history of extensions that have been installed. This way it can determine whether an extension is installed for the first time or if it is updated from an earlier installation. This, in turn, enables proper application management. (See issue #6.)

The implementation can be as simple as storing XML / text files in the Data Dictionary: one file for each extension, using the OSGI bundle's symbolic name as the filename.

Example history storage folder: /Company Home/Data Dictionary/Dynamic Extensions/Installation History

Maven project archetype

pom.xml template for creating new Dynamic Extension projects using mvn archetype:generate

Annotation-based Actions and Behaviours code review

The code for handling Actions and Behaviours is in need of a thorough review.

  • Review overall approach to using annotations.
  • Changes may result in breaking backwards compatibility.
  • Improve test coverage. (Behaviour handling has no test coverage at all!)

Dependent bundles not started in the correct order

Bundles that depend on other bundles through, for example, Import-Package are started prematurely during framework startup. These bundles are left in the INSTALLED state.

One example are bundles that depend on the Groovy runtime.

The workaround for now is to restart these bundles manually through the Control Panel.

System packages

Hi Laurens,

I used to have xx-package.txt in the classpath with:
org.apache.commons.io;1.4

For the M4 release, I renamed it to dynamic-extensions/configuration/packages/web-application-packages.txt

Packages are imported, but the version seems to be ignored. (can't remember the class responsible for this)

Is this still supported?

PS maybe store this stuff in the repo for caching & reloading ?

Web Console - Install extension

The Web Console should offer the ability to upload extension JARs using a file upload form.

The JAR should then be stored in the repository: /Company Home/Data Dictionary/Dynamic Extensions/Extensions.

While file installation is still the preferred method of managing extension, access to folders (that are accessible by the Alfresco repository server) may not always be available in enterprise environments.

Externalize configuration

Investigate approaches to externalizing configuration.

Spring supports the @Value annotation for binding bean properties and constructor arguments using Spring EL expressions:

@Value("#{systemProperties['os.name']}")
private String osName.

One approach would be to instantiate a PropertyPlaceholderConfigurer with a .properties file located using convention-over-configuration. For example a properties file matching the OSGi bundle's symbolic name.

Thinking about this some more: having access to the main Alfresco properties and other configuration from Spring EL would definitely come in handy.

Even though Dynamic Extensions favours an annotation-only approach to configuring beans, there's always the option of resorting to Spring's XML config for specialized use cases.

Prevent duplicate extension bundles

While OSGi allows for installing different versions of a given bundle, duplicate bundles containing extension code should not be permitted. This prevents the creation of duplicate behaviours, web scripts, etc.

The bundle with the highest version number should "win".

Installing duplicate library bundles (with different version numbers) should still be supported.

Spring @AspectJ not supported

Spring AOP using Java annotations is not supported: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-ataspectj

Even after adding the AspectJ runtime, which is not a part of the Alfresco distribution, to the Alfresco repository classpath, creating AOP proxies still leads to ClassNotFoundExceptions. This problem may be too hard to solve, hence this is marked as a known issue.

Supported Spring AOP strategies:

Using implementations ofAbstractAutoProxyCreator (such as BeanNameAutoProxyCreator) does work. In fact, Dynamic Extensions uses this approach to support @RunAs and @Transactional.

Untested:

AOP schema support has not yet been tested, but may work: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-schema

@Uri handler methods must have public visibility

Milestone 6 will introduce changes that require @Uri methods to be public. The current implementation does not care about method visiblity: @Uri methods can be protected or even private.

This new restriction does not apply to @Attribute or @Before handler methods.

The underlying reason for this change is to merge the annotation handler implementation with that of the Backstage project. https://github.com/lfridael/backstage

ActionDefinition.setApplicableTypes

The method arguments for ActionDefinition.setApplicableTypes changed from

List<QName>

to

Set<QName>

starting from Alfresco 4.1.2 enterprise or 4.2 community.

This means the AnnotationBasedActionRegistrar only works with < versions.

Variable expressions in Web Script URIs

To allow for flexible reuse of Web Script classes across Dynamic Extensions, the @URI annotation should allow for Freemarker variables.

Example:

@Uri("/${bundle.symbolicName}/${bundle.version}/example/{id}")
public void example(@UriVariable String id) {
}

The implementation should resolve the variables in the URI before binding the Web Script handler. At first glance the syntax for Freemarker variables does not conflict with the syntax for URI variables.

One obvious candidate for using dynamic URIs is the Resources Web Script. (Having a flexible Web Script for handling static resources would incidentally address issue #29.)

Handle exceptions from annotation-based Web Scripts

The logic should be virtually identical to how Spring MVC handles exceptions.

@ExceptionHandler(IllegalArgumentException.class)
protected void handleIllegalArgument(IllegalArgumentException ex, WebScriptResponse response) {
  response.setStatus(400); // Bad Request
  response.getWriter().write(ex.getMessage());
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.