Developer frameworks for Experience Services
Experience Services are made accessible when building an
application via a set of developer frameworks and SDKs. The frameworks
and SDKs are described below.
Experience Services - Core
Experience Services - Core is a set of frameworks at the
core of ADEP. It is comprised of three frameworks: Apache Jackrabbit,
Apache Felix, and Apache Sling.
Apache Jackrabbit is a fully conforming implementation
of the Content Repository for Java Technology API (JCR, specified
in JSR 170 and 283). This is a highly scalable Content Repository
that can be used to store and manage unstructured content such as
documents, media, user generated content, and application metadata.
Experience Services - Core does not rely on a relational database
(RDBMS); instead, it stores the content in a highly optimized manner within
the JCR content model.
Apache Felix is an implementation of the Open Services Gateway
Initiative (OSGi) R4 Service Platform and related subprojects that
implement specific parts of OSGi and related technologies.
Apache Sling is a Web framework that uses the Java Content
Repository and Felix OSGi framework to build RESTful applications
with support for scripting within the server, including JSP, server-side
For more information on each of these Apache projects that make
up Experience Services - Core, please consult their home pages:
All three frameworks within Experience Services - Core are exercised
when you build a web application using the Apache Sling framework.
Apache Sling is a web framework that uses a Java Content
Repository, such as Apache Jackrabbit, to store and manage content.
Sling applications use either scripts or Java servlets, selected
based on simple name conventions, to process HTTP requests in a
RESTful way. The embedded Apache Felix OSGi framework and console
provide a dynamic runtime environment, where code and content bundles
can be loaded, unloaded, and reconfigured at runtime. Traditional
web applications make use of Java servlets. These can also be deployed
as OSGi bundles and then used by Sling when processing an HTTP request
with endpoints that get registered for the URL path to the servlet.
As the first web framework dedicated to JSR-170 Java Content Repositories,
Sling makes it very simple to implement simple applications, while
providing an enterprise-level framework for more complex applications.
etc) that invokes application business logic deployed as OSGi bundles
(Apache Felix). Sling provides RESTful access to repository resources
(content nodes in JCR) via HTTP, as shown in this figure:
The figure below contains a detailed view of the Sling architecture:
OSGi: Java business logic for an application based
on Sling is built as a series of OSGi bundles and uses OSGi core
and compendium services. OSGi is a Java framework that provides
modularization of the server functionality. OSGi provides dynamic
loading (and unloading) of byte code in the form of bundles. OSGi
has facilities for managing bundle versioning and dependencies.
The OSGi specification is governed via an open industry alliance.
Sling API: To implement content based web applications
with Sling, an API has been defined that extends the Servlet API
and provides more functionality to work on the content.
Request processing: Sling takes a unique approach to handling
requests. A request URL is first resolved to a resource, then based
solely on that resource it selects the actual servlet or script
to handle the request.
Resources: The central idea of Sling is the resource,
which represents the resource addressed by any request URL. It is
the resource that is first resolved when handling a request. Based
on the resource, a first servlet or script is then accessed to handle
Servlets and scripts: Servlets and scripts are handled
uniformly since they are represented as resources themselves and
are accessible by a resource path.
Sling URL decomposition
Web applications written to run on Sling thus rely on JCR
nodes in the Content Repository through a process known as Sling
URL decomposition. For example, consider the following JCR node
The URL path in an HTTP request matches the location of a node
called s4 in the JCR node tree. Within that node
definition, the resource type specified points to cars under
the apps folder in the content repository. The selector (details)
and the extension (.html) from the URL are used to locate the script
that renders the page (html.jsp).
Having built an application, you need a way to bundle up
the various libraries, components, and collateral into a one deployable
unit that can be delivered to production and eventually patched
The solution is an Experience Package, which is a type
of ZIP archive with additional metadata. You can put all application
components in the package, after which the deployment process not
only explodes the zip into the server, but sorts its contents into
the correct areas of the server, including libraries (OSGi bundles),
configuration directories, and content directories. In the case
of patches or upgrades, a package can contain only the pieces that
have changed, which are overlaid onto the application being patched.
In addition, OSGi bundles can still be installed, enabled, edited,
or removed through the OSGi Console.
OSGi is the pattern used for building modular Java application
logic with ADEP through its inclusion of Apache Felix, which implements
the OSGi R4 Service Platform.
By adopting OSGi at its core, ADEP enables you to package applications
as logically independent modules, and to deploy only those pieces
needed for a given installation (solution). Applications are able
to use different versions of the same resource‚ without conflicts
or collisions, and multiple versions of the same application may
be concurrently deployed.
OSGi defines an architecture for developing and deploying modular
applications and libraries. The OSGi model is essentially a way
of managing components. A component in OSGi is a set of related
Java classes, kept together and managed as a unit. These components
are provided by a bundle.
Extending Sling with application-specific components is equivalent
to creating a bundle. A bundle is a JAR file with additional metadata.
A bundle requires a descriptor file called MANIFEST.MF (located
in META-INF). For example:
Bundle-Name: [HelloWorld] Plug-in
Note: The Java package names used in the implementing class above
must be imported. Also, the packages exposed from your bundle to
other bundles must be marked as exported.
In OSGi development it is common practice for an OSGi component
to define OSGi Services through interfaces and
implementing classes. This is provided in descriptor file references
in the MANIFEST.MF, as shown above, and located under OSGI-INF/serviceComponents.xml.
The serviceComponents.xml file defines the interface and implementation classes
used by services, and it can also describe the configuration, activation and binding behavior
of a component lifecycle:
Furthermore, the serviceComponents.xml file referenced within
a manifest can be produced from annotations when classes for the
OSGi component are compiled. This is achieved using the Apache Felix
Maven SCR Plug-in at compile time. For example, consider the following
<implementation class="org.sample.Component" />
bind="bindLogService" unbind="unbindLogService" />
<property name="p1" value="sample" />
<property name="p2" type="Integer">
These are the Java annotations for the activation phase:
These are the Java annotations for the binding phase:
These are the Java annotations for the configuration phase:
For more information about the Apache Felix Maven SCR Plug-in,
OSGi bundles, components, and services can be deployed and managed
using the ADEP OSGi Console:
Composite Application Framework
Applications built on ADEP are often made up of a variety
of content, including forms, data, charts, and video. Some of this
is Flash content, and some is HTML. Consider the behavior of the
Authors want this content not only to exist side-by-side on the
same page, but to interact. For example, clicking or typing in a
SWF should affect the appearance of HTML and vice versa. Selecting
a currency value might bring up an RSS feed of news stories in currency
markets. The Composite Application Framework is designed to address
these needs. It provides the Experience Services SDK and server
runtime for applications whose layout and modular HTML or SWF based components
are managed as content in the Content Repository provided by the Experience
Interaction between HTML and Flash
There is an object model behind the scenes that is used
in the user interface. Events, messages, and properties emitted
in Flash Player are transferred through the object model to the
HTML layer and vice versa. Each layer acts as a view of the object
model so they remain in sync and the user is presented with a consistent model.
The user interacts with both Flash and HTML content in a unified experience.
Other frameworks used by composite applications
Applications built using the Composite Application Framework
also make use of other frameworks in ADEP.
Adobe Digital Enterprise Platform Experience Services - Client Component Framework 10.0: The
Client Component Framework takes advantage of interface-based dependency
injection. Permits the use of multiple versions of the Flex SDK
used by different tiles within a composite application, if necessary.
UX Components: Reusable Flex components for which
the look and feel of a component can be tailored to the final application.
Client Component Framework
The Client Component Framework offers dependency injection
for ActionScript developers, as well as an OSGi dynamic plug-in
runtime for Flex applications. The Client Component Framework contains
two key concepts:
Bundles: Bundles are the deployment abstraction.
Physically, each bundle is a SWF.
Services: Services are the run time abstraction, referenced
using ActionScript objects.
Within bundles, there is an Application Domain Hierarchy that
is used to implement a service exposed through an interface. Each
application domain can have its own shared Flex SDK and interface
Similar in principle to an OSGi bundle used for server-side Java
business logic, a bundle defined with the Client Component Framework
contains a manifest to define services implemented or consumed by
the bundle. For example:
<?xml version="1.0" encoding="UTF-8"?>
<bundle location="my-bundle.swf" loader="flex-application">
UX components employ a design where the component is separate
from its skin and uses interfaces and domain objects to communicate
with remote services. The component can be inherited for specialization,
and because its skin is separated from the component, the look and
feel of the component can be tailored to the final application.
Separating the component into presentation layer, domain model,
and services eases configuration and reuse. The Client Component
Framework can be used to load different components into an application
at runtime, and to inject service implementations into the component,
such as different data sources or alternative business logic.
There are several key points about UX components:
UX component has replicable skins and styles (presentation layer).
Interfaces are used in front of the implementation of services
consumed by the UX component.
Services are injectable using the Client Component Framework.
Applications based on content
Experience Services - Core provides three essential capabilities:
an application framework, an application runtime, and a content
repository. The RESTful nature of the application framework (Sling),
the modular (OSGi-based) nature of the application runtime (Felix),
and the node-oriented nature of the open standards (JCR 2.0) compliant
content repository provide a robust foundation for composite applications.
By thinking of both SWFs and HTML as content, you can use your
favorite authoring environments to create components and tiles.
That content is then deployed into a catalog on a server. From there
it is composed into applications that are tailored for delivery
to the user. The platform-specific application provides the tailored
navigation tuned to the device, while sharing content across platforms.
Data Services is a server-side framework that offers the
following capabilities to Flex applications, including mobile applications
built using Flex:
Remoting: Allows Flex client
applications to invoke methods on Java server objects directly.
Similar to Java remote method invocation (RMI), remoting handles
data marshalling automatically and uses a binary data transfer format.
Messaging: Provides the publish portion of the publish/subscribe
design pattern. The Flash client can publish events to a topic defined
on the server, and subscribe to events broadcast from the message
Data Management: Provides a programming model for
automatically managing data sets that have been downloaded to the
Flex client. Once data is loaded from the server, changes are automatically
tracked and can be synchronized with the server at the request of
the application. Clients are also notified if changes to the data
set are externally updated. The server communicates with the client
to present live data to subscribed clients.
Data Services has been traditionally deployed as a Java EE application
(formerly known as LiveCycle Data Services). Now it is a central
component within ADEP using Apache Sling and OSGi, which makes possible
the new behavior and capabilities summarized below.
For a developer already familiar with Data Services from previous
releases, the following topics should be understood for Data Services
Use of OSGi
Integration with SQL Data Sources
Using JCR as persistence for Data Management
Current restrictions on protocols
Data Services uses the Content Repository to mange its
configuration files (under /etc/aep/config/dataservices).
For example, this includes Data Services Remoting destinations.
In addition to simply hosting configuration files in CRX, it
is also possible to provide incremental XML snippets of additional
configuration under the /etc/aep/config/destinations folder.
This means that a base configuration can be maintained, but individual
applications deployed through Experience Packages can carry additional
configuration for the needs of one application.
Use of OSGi
In order to expose a Java class for Remoting with Data
Services, the Java class must be deployed through an OSGi bundle,
typically as part of an Experience Package. In addition, it is possible
to enable Remoting for a Java class by using an OSGi configuration
property in its bundle, instead of relying on explicit configuration
using the Data Services XML configuration files.
In the example below, the osgi-context.xml file is placed under
the /META-INF/spring folder of an OSGi bundle in
which a Java class is used for remoting:
In this example, the osgi-context.xml defines a remote object
for a Spring
bean within the bundle identified by lc.processmanagement.taskManagerImpl
The OSGi service is defined as a bean element defined in the Blueprint
<?xml version="1.0" encoding="UTF-8"?>
<bp:service ref="lc.processmanagement.taskManagerImpl" auto-export="interfaces">
<entry key="connectors.remoting.id" value="taskmanagement.taskManager" />
<entry key="implementation.type" value="standard"/>
Integration with SQL data sources
In order to use SQL data sources with Data Management,
the data sources must be configured under new entries for the JDBC
Connections Pool in the OSGi Console. For example, here is a JDBC
Connections Pool at http://localhost:4502/system/console/configMgr:
Each JDBC data source is then assigned settings, as shown in
the following example:
The JDBC driver class used for a JDBC data source must also already
be deployed in an OSGi bundle. JDBC drivers that you might have
already as plain JAR files must be converted into OSGi bundles,
for example, by using the Apache Felix Bundle Plugin for Maven,
which is available at http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html.
Using JCR as persistence for Data Management
Data Management allows you to author a data model in Flash
Builder and deploy it to the Experience Server. This creates new
Data Services destinations, which expose CRUD (create, read, update
delete) and filter operations for the entities in the data model.
At runtime, these operations are implemented on the server by a
Data Services Assembler that traditionally has used Hibernate to
manage data in a SQL database.
As part of Data Services with ADEP, an option is available to
use the Content Repository for persistence in an application built
using Data Management. This is supported by a new Data Services
Assembler built using JCR. This option is enabled by authoring a
data model in Flash Builder with a Preference set to use the Content
Repository as the Deployment Handler for persistence, as shown in the
At run time, instance data created by your application, based
on entities in the data model, are stored in a JCR node tree, as
shown in the following example:
Current restrictions on protocols
Experience Services - Data Services currently does not
support the RTMP protocol, and does not support HTTP Java New Input/Output
(NIO) Endpoints using a NIO-based socket server.
The Experience Server provides the following capabilities
for Task Management, utilized by developers as part of the Experience
A framework to manage the lifecycle of User
Tasks. The framework provides two default provider implementations
for User Tasks; one using content in the Content Repository and
one using the Document Server running a business process management
process. Regardless of the implementation chosen, the APIs and UX
components used by the web application do not need to change. This
approach permits other custom providers to be written for integration with
third party task management systems. The two implementations are:
Stand-alone User Task: A Stand-alone User Task can
be assigned to users with custom properties, payload and status.
These User Tasks do not need to originate from a BPM process. Instead,
they can be created and assigned in an ad-hoc fashion by applications
that manage appointments or To-Do items for their end users. Stand
Alone User Tasks are managed in the CRX Repository as data in a
JCR node tree.
Document Server User Task: User Tasks are generated
by a business process management process running on the Document
Server, using Process Management. Web applications deployed on the
Experience Server can use the Task Management framework to access
and manage these User Tasks through the same set of UX components
used to manage Stand-alone User Tasks.
A set of UX components available in Flash Builder to help
build applications that manage User Tasks and display the work payload
of a User Task.
A set of services (exposed via Data Services Remoting) that
can be used in Flex applications to interact with Stand-alone and
Document Server User Tasks.
The Task Management framework provides the following UX
components, distributed via the ADEP Experience Services SDK. These
UX components are:
Task Document Submit
Web Document Viewer
The naming pattern in each of the UX components above is <Function Name> and <Function Name>Component.
The difference between each is that the Component variation
consumes a Service Interface used as a Flex Data Provider for the
UX Component. For example the TaskListComponent uses an ITaskManager,
which offers query operations (for example, getTasks() calls
the UX Component to fetch a list of ITask Objects). The simpler TaskList just
uses a statically supplied list of ITask Objects.
Each UX component provides a set of libraries that correspond
to the UX design pattern discussed above. These libraries provide
the domain logic, a component wrapper, a service, and one or more
skins. For example, in the case of the Task List UX component:
task_list_domain.swc (domain logic)
task_list_component.swc (UX component wrapper)
task_list_ui_service.swf (Service implementation)
task_list_datagrid_skin.swc (custom skin)
Note: The Task List and Task Details UX components can be used with
either Stand-alone User Tasks or Document Server User Tasks. However,
the UX components for Task Attachments, Task Action, and Task Document
Submit are only used for Document Server User Tasks since that is
what their service implementation supports. Their service implementation
relies on the Experience Server having been configured to access
a Document Server for retrieving User Task information, and will do
so based on the identity of the user who has been authenticated
to the Experience Server.
Task Management Services
The Experience Server exposes a set of services that applications
can use through a Client SDK to manage User Tasks. These services
are visible in the OSGi Console.
The Task Management services are:
ITaskManager: Exposes a standard API for managing
User Tasks (Stand-alone or Document Server based).
ITaskTypeRegistry: Exposes a standard API for managing
User Tasks (Stand-alone or Document Server based).
ILCTaskManager: Exposes a set of operations specific
to managing Document Server User Tasks.
TaskDao and TaskTypeDao: These services are
an implementation of the interface used to persist and query Stand-alone
User Tasks. Their default implementation uses JCR for the Content
Repository, but other custom implementations are possible.
Access to the Task Management services is provided through the
Task Management Client SDK supplied as part of the overall Experience
Configuring Stand-alone Tasks
ADEP provides a server-side framework and Experience Services
SDK designed to address typical security related requirements during
the development of rich Internet applications:
authentication using either the Content Repository or a Document
Server as the provider of user identity. There is also a plug-in
model based on the Java Authentication and Authorization Service
(JAAS) for delegating authentication to other identity providers.
Single Sign-On and identity propagation for an already logged-on
end user across all Experience Services. For example, when a client
application is invoking Data Services, accessing Composite Application
Services or making HTTP Requests using Apache Sling, re-authentication
is not required.
Client access to the user details for the current logged
in user with the notion of an ActionScript User object. This includes
access to any third party tickets and assertions used to authenticate
the user against an external system.
Client access to SSO cookies and a SAML Assertion or the
current logged in user. This is typically needed when services are
accessed across multiple domains, thus preventing cookie-based authentication.
Handling a session time-out in a Flex application and triggering
a custom method to re-authenticate the user.
Client access to roles and permissions for the logged in
Log out handling.
Considerations for authentication
Applications built on the Experience Server must authenticate
their users via the Sling Web framework. In general, there are two
ways to accomplish this, based on either HTML or Flex.
Authentication using HTML
Applications can authenticate an HTTP request using a standard
HTML form, in which the action for a POST is set to use to /j_security_check
The Form supplies a sling.auth.redirect
the page to be redirected after successful authentication. The following
example shows this as a snippet from a typical HTML form:
method="post" accept-charset="UTF-8" enctype="application/x-www-form-urlencoded">
<table width="96%" border="0" summary="Enter User ID and Password" cellspacing="2" cellpadding="2">
<td align="center" nowrap="nowrap" colspan="2" class="boldText">
<font face=tahoma size=4>Please Login</font>
<td align="center" nowrap="nowrap" colspan="2" class="boldText"> </td>
<td align="right" class=""><font face=tahoma size=3>User ID: </font></td>
<input name="j_username" id="loginName" type="text" value="" width="200"/>
<td align="right" class=""><font face=tahoma size=3>Password: </font></td>
<td align="left"> <input name="j_password" type="password" value="" width="200"/></td>
<input type="hidden" name="sling.auth.redirect" value="/content/myapp/welcome.html" />
<td height="40" class="noBorderCell" align="center" colspan="2">
<input type="submit" class="buttonGenericPrimary" value="Login"/>
Authentication using Flex and Data Services
For building Flex applications using ADEP, a Security Client
API, provided as part of the Experience Services SDK, allows a Flex
application to authenticate using Apache Sling. This is particularly
important when using Data Services in ADEP, as the traditional Flex ChannnelSet.login() and ChannelSet.logout() will
not work in this scenario.
In the example code snippet below, the call to securityManager.performSSO()
whether the end user has already been authenticated and, if not,
triggers a call to authenticate the user using securityManager.login()
<s:Application .. creationComplete="initApp()">
protected var securityManager:SecurityManager;
public function initApp():void
var securityConfig:SecurityConfig = ConfigUtil.getDefaultRIASecurityConfig();
securityManager = SecurityManager.getInstance(securityConfig);
var token:IToken = securityManager.performSSO();
private function loginHandler(ar:IAuthResult):void
private function loginCommand():void
status("logging in with username:" + username.text + " and password: " + passwd.text);
var token:IToken = securityManager.login(username.text, passwd.text);
When a Flex application uses Data Services to invoke a Remote
Object deployed on ADEP, additional configuration is necessary for
Data Services in order to enforce authentication via Apache Sling
for invocation requests between the Flex application and the Data
Services Destination used by the Remote Object.
To define a security constraint, in the services-config.xml file
(found in the repository at /etc/aep/config/dataservices
add a security constraint to the <security> section of the
<login-command class="com.adobe.lcds.sling.impl.SlingLoginCommand" server="Sling"/>
In the destination configuration, reference the security constraint:
<security-constraint ref="sample-users" />
Document Server integration
Experience Server is integrated with the Document Server
in two ways:
Ability to use Document Server as the Identity
Provider for authentication and group membership of users who authenticate
to the Experience Server. This is achieved by enabling a CRX Login
Module supplied with ADEP that performs authentication using a separately
deployed Document Server. Authentication is controlled by an Enterprise
Domain on the Document, based on LDAP or locally administered users.
Invocation of Document Services and processes running on
the Document Server via the Document Services SDK. This SDK can
be used within an OSGi bundle or via scripting in a JSP.
In addition, you can use the Content Repository Connector to
allow Document Services to use Experience Services as a repository.
For more information about this Document Services Component (DSC),
see The Content Repository Connector DSC.
Use the Experience Services SDK to invoke Document Services
Before a web application deployed on the Experience Server
can invoke Document Services, the Experience Server must be configured
with the location of the Document Server as well as a user account
that it can use to perform system privileged operations on the Document
Server (in cases where the Document Server is not invoked under
the identity of a logged on end user). This bootstrap is achieved
by running an auto-configuration tool in the OSGi Console and supplying
a Document Server Administrator credential used to log into the Document
Server during the bootstrap phase.
After running the Configure option, a new configuration property
is created under /apps/docservices/config in the
JCR Node tree containing the properties needed by the Experience
Server to invoke Document Services on the Document Server:
Once the Experience Server is configured to connect to the Document
Server there are two common ways to invoke Document Services:
Calling Document Services from a JSP
The snippet below shows the basic pattern for invoking
a Document Service from a JSP. With this pattern, the Document Service
will be invoked based on the user identity of the end user logged
on to the Experience Server with authentication configured to use
the Document Server.
SlingScriptHelper scriptHelper = bindings.getSling();
ServiceClientFactoryProvider scfp = scriptHelper.getService(com.adobe.livecycle.dsc.clientsdk.ServiceClientFactoryProvider.class);
ServiceClientFactory scf = scfp.getDefaultServiceClientFactory();
[HashMap]<String,Object> hmInput = new [HashMap]<String,Object>();
: Required input parameters can be set here
[InvocationRequest] ir = scf.createInvocationRequest(MyService, MyOperation, hmInput, true);
[InvocationResponse] iresp = scf.getServiceClient().invoke(ir);
Object output = iresp.getOutputParameter(outputValue);
For additional information, see Integrate with Document Services .
Calling Document Services from an OSGi bundle
Java logic for a web application must be deployed as an
OSGi bundle, as discussed the previous section. In order to use
the Document Services SDK from within a bundle, it is necessary
to inject a Service Client Factory that will be used within your
Java implementation to invoke the Document Service. In this snippet,
the behavior is to invoke the Document Service as the end user who
is logged into the Experience Server, using the Document Server
First the osgi-context.xml defined within the bundle must define
the Service Client Factory that will be injected into the Java Class,
within your application, that needs to invoke a Document Service:
factory-bean="serviceClientFactoryProvider" factory-method="getDefaultServiceClientFactory" scope="prototype">
<bean id="lcinvoke" class="com.myapplication.InvokeServiceSingleImpl">
<property name="svcClientFactory" ref="serviceClientFactory" />
<bp:service interface="com.myapplication.InvokeServiceSingle" ref="lcinvoke">
<entry key="connectors.httpinvoker" value="true" />
<entry key="connectors.httpinvoker.id" value="/lcinvoke" />
Then, within your implementation class, you use the Document
Services SDK with the injected Service Client Factory to invoke
the Document Service:
public class InvokeServiceSingleImpl implements InvokeServiceSingle
public ServiceClientFactory scf=null;
public void setSvcClientFactory(ServiceClientFactory scf)
this.scf = scf;
public ServiceClientFactory getSvcClientFactory()
public InvokeServiceSingleImpl(ServiceClientFactoryProvider svcP)
this.scfP = svcP;
public String invokeMyDocumentServiceString subject, String body)
HashMap<String,Object> hmInput = new HashMap<String,Object>();
InvocationRequest ir = scf.createInvocationRequest("MyApplication/MyDocumentService", "invoke", hmInput, true);
InvocationResponse iresp = scf.getServiceClient().invoke(ir);
Object output = iresp.getOutputParameter("outForm");