Synthetic Models are not a new concept – but the concept is rarely used when developing in AEM/Sling/JCR.
They
Define domain objects where the domain is not exclusive to the content repository
Their property collection is defined against the data from each data source
Must be orchestrated by Sling’s resource resolution mechanism
Leverage the Presentation Model design pattern
Name is inspired by the SyntheticResource class
This definition came out of several past experiences where data from external sources was required to be brought into AEM and exposed to the presentation layer as if it was content.
Also through research on the problem I cam upon the SyntheticResource class. Think of it as the lesser-known cousin of Resource. It is often used to define resource objects that don’t exist in the JCR content tree or resources that are created at run-time
3. • Traditional web frameworks
– Resolve a Controller based on the data type
– Elaborate mechanics to load the data
• Sling
– A web framework based entirely on REST principals
– The data is at the center or the process
– Everything is a Resource
4. • Sling maintains a virtual tree of resources
• Each Resource type has a ResourceProvider which provides the root of its
resolution path
• Resource types in the tree
– JCR nodes
– File System
– Bundles
– Servlets
– Other (Non-JCR) Resources
System provided
5. • Resolving a Resource is simple
The
ResourceResolver
takes in the resource
path
6. • Resolving a Resource is simple
It identifies a
suitable
ResourceProvider
The
ResourceResolver
takes in the resource
path
7. Which calls it’s
getResource
method
• Resolving a Resource is simple
It identifies a
suitable
ResourceProvider
The
ResourceResolver
will take in the
resource path
8. And provide us
with the right
Resource
Which calls it’s
getResource
method
• Resolving a Resource is simple
It identifies a
suitable
ResourceProvider
The
ResourceResolver
takes in the resource
path
9. • Resource is a central concept to Sling
• Has a number of essential properties
– Including a reference to the rendering script
• Can be adapted to other compatible types
• It’s the starting point in any domain modelling in Sling
11. • With Sling, domain modelling should be done against resources
• Each Resource is a collection of properties
– Entirely defined in the repository
– Uniquely identified by it’s sling:resourceType
• The domain model thus is a representation of the type and properties
12. • There are MANY ways to implement your domain model
– Direct access to resource properties from the view
– A custom mapping framework
– Cognifide’s Slice framework
– Sling Models (available in AEM6 as a standard)
– Neba.io My new favorite!
13. What if your domain is NOT uniquely defined in the repository?
• Legacy Apps
• 3rd party services
• CRMs
• ERPs
14. Ask yourselves:
• How do we bring this data into our application?
• How do we expose it to the UI?
• How do we maintain Sling’s RESTful principles?
question mark on road: image via Flickr/ milos
milosevic
16. • Synthetic Models
– Define domain objects where the domain is not exclusive to the content
repository
– Their property collection is defined against all data sources
– Must be resolvable by Sling’s resource resolution mechanism
– Leverage the Presentation Model design pattern
– Name is inspired by SyntheticResource
17.
18. • Synthetic Model
– They inherently rely on Sling’s resource resolution mechanism
– A ResourceProvider is required for each external domain object
• Think of this as writing a service to expose the external data
– These ResourceProviders will return either an instance of SyntheticResource or
a custom Resource implementation
• I’d advise caution when deciding on a custom Resource implementation
19. Writing your Synthetic Models with Neba.io
• Using Neba.io makes it easy!
– In reality you can achieve this with most of the mapping frameworks especially
Sling Models
• Annotation driven
• Integrates the Spring Framework in Sling
• Main features
– Resource Models
– Spring MVC
20. @ResourceModel(types = "/apps/synthetic-models/components/book")
public class Book {
@This
private Resource resource;
@Path("/content/book-store/bookinfo/${isbn}")
private Resource bookInfo;
private String isbn;
private String imagePath;
private String title;
private String description;
private String genre;
private String author;
The Synthetic Model
A JCR resource reference
External resource reference
Synthetic Model Example
21. ResourceProvider example
@Component(metatype = false)
@Service
@Properties({
@Property(name="service.description", value="A DB backed Book Resource"),
@Property(name="service.vendor", value="Odecee Pty Ltd"),
@Property(name=ResourceProvider.ROOTS, value="/content/book-store/bookinfo"),
@Property(name=SlingConstants.PROPERTY_RESOURCE_TYPE, value="/apps/synthetic-models/
components/book/book.jsp")
})
public class BookResourceProviderImpl implements BookResourceProvider {
Ever since the first time I installed AEM or CQ5 two things stood out for me: it took 5 minutes to get it going especially considering that I was also trying to setup Oracle’s WebCenter sites for an ongoing project for two days and it’s resource resolution.
While everyone appreciates a system that’s this easy to stand up, it’s the resource resolution that was the main attraction foe me. You see, the first project I ever worked on as a developer was a custom built CMS that, as any other Java web application 10 years ago, relied on Tomcat, a database and XML. And at the heart of it was a class called DummyXMLCapable. This class was responsible for parsing through the stored XML object, resolving each component and transforming it to it’s HTML form. And it was complex beyond anything I’ve seen until then but truly remarkable! It made our work, which was to enhance the available components portfolio, significantly easier. All we needed to do was write the component code and the system knew how to interpret and resolve it. This is exactly what I saw in Sling’s resource resolution and what initially drew my attention to the “Everything is content” paradigm.
So why is resource resolution so important?
Traditional Web Application frameworks employ fairly elaborate methods to select a Servlet or Controller based on the data type identified from the request, which in turn tries to load some data (usually from a database) to act upon and finally to somehow render the result.
Sling turns this process around in that it places the data to act upon at the center by using the request URL to first resolve it before identifying the script that will render it. This data is internally represented as an instance of the Resource API. Based on the resolved resource type as well as it’s properties Sling select a script or servlet that will handle the processing or rendering. Hence in Sling “Everything is a Resource”.
Sling maps the content repository as a virtual tree of resources based on their path.
This concept revolves around two API’s – the ResourceResolver which is used to resolve Resources and the ResourceProvider that is used by the ResourceResolver to transparently access resources across different locations.
There are four system provided types of resources:
JCR nodes
File system resources
Bundles
Servlets
Sling allows for non-JCR resources to be mapped in the tree
This slide: First instruct the ResourceResolver to find a resource based on it’s path
Next slide: The resolver finds the ResourceProvider whose root path matches closest to the path provided
The resource provider provides the resource by calling it’s own getResource method
Which will provide the right Resource
First instruct the ResourceResolver to find a resource based on it’s path
This slide: The resolver finds the ResourceProvider whose root path matches closest to the path provided
Next slide: The resource provider provides the resource by calling it’s own getResource method
Which will provide the right Resource
First instruct the ResourceResolver to find a resource based on it’s path
The resolver finds the ResourceProvider whose root path matches closest to the path provided
This slide: The resource provider provides the resource by calling it’s own getResource method
Next slide: Which will provide the right Resource
First instruct the ResourceResolver to find a resource based on it’s path
The resolver finds the ResourceProvider whose root path matches closest to the path provided
The resource provider provides the resource by calling it’s own getResource method
This slide: Which will provide the right Resource
Given resource resolution is one of the main features of Sling, the Resource API is definitely one of it’s core concepts
The Resource API provides several essential properties including the type of the resource, the path or the location in the virtual tree, it’s name, the super type or the type of the parent if applicable (where is this used?), and resource metadata which we will leverage in the demo.
The Resource API follows the adapter pattern defined in Sling by providing an adaptTo method which allows for a Resource object to be adapted to an instance of any compatible class.
It is also the starting point in any domain modelling or domain mapping concept in Sling
So what happens when you want to define a domain model using the Resource API in Sling?
A colleague of mine wrote an exceptionally lightweight and functional mapping framework that we’ve successfully used in many projects.
We used Slice in a project for a major client but I personally found it a bit bloated and sluggish.
Sling Models is also available as a standalone bundle that you can retrofit in older versions of AEM (5.6+)
Today’s enterprise solutions are more often than not realised through multiple systems which from a business perspective are expected to work as a single entity, which means that information from one system should be “seamlessly” available in other systems. Sometimes this is easy to achieve, for example, synchronising your product data from Hybris into AEM or customer information between AEM and Salesforce as there are built in adapters that make it possible. But what about legacy apps or 3rd party services that your clients can use to “enhance” the product information they provide? These require development efforts that can be significant to make available.
Usually, when our data is located in a system that’s not directly accessible by our AEM package via a ready-made adapter, the way to solve this problem is by implementing a service that will wrap around the data source endpoint and a separate domain model that maps to the expected output of the data source. Now, while this is perfectly fine as a solution it does have some drawbacks in the AEM world and it’s technology stack. The service calls would need to be mapped in the dispatcher and allowed through, the data brought in this way won’t be content authorable (should that be a requirement), the UI will be tightly coupled to the service you just wrote.
Synthetic models are a simpler and cleaner way to not only bring in this external data into your domain but also expose it to AEM in such a way that’s easy for it’s technology stack to understand and action it.
Synthetic Models are not a new concept – but the concept is rarely used when developing in AEM/Sling/JCR.
They
Define domain objects where the domain is not exclusive to the content repository
Their property collection is defined against the data from each data source
Must be orchestrated by Sling’s resource resolution mechanism
Leverage the Presentation Model design pattern
Name is inspired by the SyntheticResource class
This definition came out of several past experiences where data from external sources was required to be brought into AEM and exposed to the presentation layer as if it was content.
Also through research on the problem I cam upon the SyntheticResource class. Think of it as the lesser-known cousin of Resource. It is often used to define resource objects that don’t exist in the JCR content tree or resources that are created at run-time
Lets say that we need to display information about a book. The information is partially in the JCR and partially in an external data source, in this case a database.
We define our BookSyntheticModel as the model of our component. The component is aware of the properties the model provides but not where they are coming from so they are completely encapsulated by our Synthetic Model.
The BookSyntheticModel interacts with both the JCRBook and the DBBook Resource to provide a single properties collection to the component.
Custom Resource implementations should be achieved by extending the ResourceWrapper or the AbstractResource classes to ensure that all methods of the Resource interface are implemented even when the API gets updated
NEBA integrates the Spring Framework into Sling.
It makes available all of Spring's features to allow using mature, best-practice solutions for the majority of system-level concerns common to Sling-based applications.
NEBA does so in full compliance with the open core philosophy - using exclusively mature, standardized open source software - gemini blueprint - for the integration into OSGi.
All Spring and Sling features are accessible to developers using a lightweight, well documented API that does not couple the domain -specific implementation code to any implementation details of Sling, Spring or NEBA.
Principles:
Zero interference: Do not alter any Sling or system behavior
Zero coupling: Software using NEBA must not depend on NEBA implementation code and vice-versa.
Further composition: Allow transparently using NEBA from standard Sling components and vice-versa.
Further best practices: Guide users towards using REST and adapter factories, leverage the Sling resource type system
Semantics first: Users shall express intent using @Semantic annotations instead of implementing or providing configuration.
Be optional: Users may or may not decide to use NEBA
So lets combine all the pieces and see how a Synthetic model would look like.
As you can see from the code it doesn’t look much different from any other model. The only difference is the extra Resource that we’re bringing into our class that represents the external book data source.
So lets combine all the pieces and see how a Synthetic model would look like.
As you can see from the code it doesn’t look much different from any other model. The only difference is the extra Resource that we’re bringing into our class that represents the external book data source.