1. What is Adobe CQ5? (now Onwards AEM5.6-Adobe Experience Manager 5.6 )What is CQ5? What is a Content Management System?
CQ5 is a java based content management system from adobe, previously Day CQ5.
1) It is based on a content repository(i.e it uses a content repository to store the content of a website) and use JCR(java content repository) specification to access the content repository.
2) It uses RESTful Apache Sling framework to map request url to the corresponding node in content repository
3) it uses powerful OSGi framework internally to allow modular application development. It means individual pieces of your application(called bundles in terms of OSGi) can be independently started and stopped. CQ5 uses Apache Felix as the OSGi container. Therefore different parts of cq5 can be independently started and stopped.
Coming to
why a content management system is required? Some websites are very
dynamic in nature, content needs to be updated frequently, so it is
easier to manage the content of such websites using a CMS.
Adobe
CQ5 platform allows you to build compelling content-centric
applications that combine Web Content Management, Workflow Management,
Digital Asset Management and Social Collaboration. The product has been
completely redesigned from Communiqué 4, allowing Adobe to use new
architecture and technologies, thus increasing functionality while
reducing complexity. Extensive use of standards helps ensure long-term
stability.
Adobe
CQ5 is geared specifically for large companies and corporations with
substantial -and often global- infrastructures. It combines web content
management, digital asset management, and social collaboration to
deliver a solution that allows large companies to manage incredible
amounts of information, multiple internal and external websites, a
myriad of media assets, and detailed workflow
2. What is the technology stack of cq5?
Cq5 uses the following technologies :
1) JCR –
java specification for accessing a content repository JSR-283
specification jcr 2.0 , cq5 uses its own implementation of jcr called
CRX. Apache Jackrabbit is an open-source implementation of jcr 2.0
specification.
2) Apache Sling – RESTful framework to access a jcr over http protocol. It maps the request url to the node in jcr.
3) OSGi – framework for modular application development using java. Each module called bundle can be independently started and stopped.
2) Apache Sling – RESTful framework to access a jcr over http protocol. It maps the request url to the node in jcr.
3) OSGi – framework for modular application development using java. Each module called bundle can be independently started and stopped.
3. What is a content repository? What is JCR?
A Content
repository is basically a place where digital content is stored.
Generally the structure of the content repository is hierarchial and
represented as a tree structure where each node of the tree is used to
store content. Java Content Repository is a specification provided by
the java community to access the content repository in a uniform way
(platform independent and vendor independent way). The specification was
initially released as JSR-170(JCR 1.0) and then later revised version 2
as (JCR-283).
The javax.jcr API provides the various classes and interfaces to access a content repository
Apache Jackrabbit is an open-source implementation of JCR- 2.0 specification.
It provides some wrapper classes and interfaces specific to jackrabbit plus many more functionalities on top of jcr.
The org.apache.jackrabbit packages are used to access Jackrabbit.
4. What is REST? What is a RESTful Framework?
REST stands for Representational State Transfer.
According to the REST architecture, there are 6 constrainst which should be followed:
Client-Server
There should be a clear separation between a client and server.
There should be a clear separation between a client and server.
Stateless
The
client-Server communication is further constrained by no client context
being stored on the server between requests. Each request from any
client contains all of the information necessary to service the request,
and any session state is held in the client. The server can be stateful
Cacheable
As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.
As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.
One more
thing which differentiates as RESTful framework from other
web-development frameworks is that generally all web-development
frameworks rely heavily only on HTTP Get and Post Requests. While a
restful leverages the maximum of http protocol. It uses all the types of
http request(HEAD,GET,POST,PUT,DELETE).
For example - consider a scenario where you want to delete a product from a product list with product_id=111;
The server
side code for the same will be somewhat like this if a HTTP GET request
is sent from client-browser with product_id=111 appended to the url.
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
String prod_id = req.getParameter(“product_id”);
Connection con = DBConnection.getConnection();
Statement st = con.createStatement();
st.executeQuery(“delete * from product where product_id=’”+product_id+”’”);
}
As you can
see In the above piece of code, we are using a GET request to perform a
delete operation on a resource. Therefore we are not using the real
power of HTTP protocol. According to REST principles, the same could
have been done by sending a HTTP DELETE request from client browser and
at server side.
public void doDelete(HttpServletRequest request, HttpServletResponse response)
{
{
String prod_id = req.getParameter(“product_id”);
Connection con = DBConnection.getConnection();
Statement st = con.createStatement();
st.executeQuery(“delete * from product where product_id=’”+product_id+”’”);
}
Similarly to read a resource – use GET – scenario – get product details
create a new resource – POST – scenario – add a new product
update a resource – PUT - scenario – update an existing product details
get product meta information – use HEAD – scenario – reading the meta-information of products (say inventory information.
create a new resource – POST – scenario – add a new product
update a resource – PUT - scenario – update an existing product details
get product meta information – use HEAD – scenario – reading the meta-information of products (say inventory information.
REST is
nothing but using the current features of the “Web” in a simple and
effective way. If you see, some of the amazing features of the Web are:
ñ40 years old matured and widely accepted HTTP protocol.
ñStandard and Unified methods like POST, GET, PUT and DELETE.
ñStateless nature of HTTP protocol.
ñEasy to use URI (Uniform resource identifier) format to locate any web resource.
REST leverages these amazing features of the web with some constraints.
Let’s
define REST in official words, REST is an architectural style built on
certain principles using the current “Web” fundamentals.
There are 5 basic fundamentals of web which are leveraged to create REST services.
Principle 1: Everything is a Resource
Internet is
all about getting data. This data can be in a format of web page,
image, video, file, etc. It can also be a dynamic output like get
customers who are newly subscribed. The first important point in REST is
start thinking in terms of resources rather than physical files.
Below are some examples of resources with URI:
www.questpond.com/image/logo.gif (Image resource)
www.questpond.com/Customer/1001 (Dynamically pulled resource)
www.questpond.com/videos/v001 (Video resource)
www.questpond.com/home.html (Static resource)
So the first thing is, visualize everything as resource.
Principle 2: Every Resource is Identified by a Unique Identifier
The old web identifies all resources by a URI. For instance, if you want to display customer with their orders, you can use www.questpond.com/DisplayCustomerandOrder.aspx. In REST, we add one more constraint to the current URI, every URI should uniquely represent every RESOURCE data.
For instance, you can see the below unique URI format for customer and orders fetched.
Customer data
|
URI
|
Get Customer details with name “Shiv”
|
http://www.questpond.com/Customer/Shiv
|
Get Customer details with name “Shiv”
|
http://www.questpond.com/Customer/Shiv
|
Get Customer details with name “Raju”
|
http://www.questpond.com/Customer/Raju
|
Get orders placed by customer "Shiv"
|
http://www.questpond.com/Customer/Shiv/Orders
|
Get orders placed by customer “Raju”
|
http://www.questpond.com/Customer/Raju/Orders
|
Principle 3: Use Simple and Uniform Interfaces
Simplification
is the way to success and that’s what exactly the goal of uniform
interfaces is. When external clients are interacting with web resources,
they expect simplified interfaces.
For
instance, let’s say you have exposed customer and orders data / resource
on the web. Let’s assume below are the methods / function names by
which external clients can communicate to your application.
AddCustomer
InsertOrders
SelectCustomer
getOrders
DeleteCustomer
RemoveOrders
UpdateCustomers
Do the
above method names look inconsistent and difficult to remember? Yes they
do. Now what REST says is keep your interfaces uniform and simple. This
can be achieved by using the uniform methods of HTTP protocol and
combining the same with your resource operation.
Below is the list of HTTP methods for getting, creating, updating and deleting a resource on the web.
Methods
|
Description
|
GET
|
Get a resource
|
PUT
|
Create and Update a resource
|
DELETE
|
Deletes a resource
|
POST
|
Submits data the resource
|
Now by
combining the standard HTTP methods and your resource names, you can
have uniform interfaces and thus leading to simplified communication.
You can see from the below table how we have created uniform REST URL
using standard HTTP methods.
Normal Method names
|
HTTP methods
|
REST Uniform URL
|
AddCustomer
|
PUT
|
Customer/Shiv
|
InsertOrders
|
PUT
|
Orders/1001
|
SelectCustomer
|
GET
|
Customer/Shiv
|
getOrders
|
GET
|
Customer/Shiv/Orders
|
DeleteCustomer
|
DELETE
|
Customer/Shiv
|
RemoveOrders
|
DELETE
|
Customer/Shiv
|
UpdateCustomers
|
PUT
|
Customer/Shiv
|
Principle 4: Communication is Done by Representation
When you send any request or you get any response, you are actually sending representations. For example, let’s say you want to create a new customer record, you would send some kind of representation as shown below using HTTP PUT.
<Customer>
<Name>Questpond.com</Name>
<Address>Mulund Mumbai</Address>
</Customer>
<Customer>
<Name>Questpond.com</Name>
<Next>http://www.questpond.com/Customer/Questpond/Orders</Next>
</Customer>
The above
representation was in XML format. If you wish, you can also send and
receive other presentations like JSON. For instance, below is a simple
JSON snippet for creating a new customer record with name and address.
{Customer :{ Name:'Questpond.com', Address:'Mulund Mumbai'}}
Principle 5: Be Stateless
Every
request should be an independent request so that we can scale up using
load balancing techniques. Independent request means with the data also
send the state of the request so that the server can carry forward the
same from that level to the next level.
For instance, below are two simple representations, the first representation is sent for logging in.
<Login>
<Name>Questpond.com</Name>
<Password>sdkj#43445</Password>
</Login>
If you are logged in successfully you receive the below representation.
<Login>
<Success>true</Success>
</Login>
If you want to search for customer,
you would send him the below representation stating that you are in a
state of successful logging in and would like to search all customers.
<Customer>
<Filter>All</Filter>
<Success>true</Success>
</Customer>
In other words, every request is independent and the server does not need to remember your previous request and states.
5. What is Sling? How is it different from other web-development frameworks?
Apache Sling is RESTful framework to access a java content repository over http protocol.
It is a
content driven framework that is it maps the incoming user request based
on URI to the corresponding node in the content repository and
depending on the type of the request(GET,POST, etc) executes the
corresponding dynamic script.
For example - consider a scenario where a user is hitting a US website products page and getting the details of product1.
The incoming URL request from user will be
www.mywebsite.com/products/product1.html
This would be mapped by the sling resource resolver to a node in the JCR
/content/mywebsite/us/products/product1
Now the
Sling resource resolver will check the properties of this node and check
the sling:resourceType property of this node, which will tell the
script that will be used to render the content of this page.
For example if value of sling:resourceType property is /apps/mywebsite/products/GET/body.jsp
Then for all the incoming GET requests on the product1 node, the above script will be used to render the content.
The main advantages of sling are:
The main advantages of sling are:
it maps the url directly to the content
it is restful.
it is restful.
6. How is resource resolution done in Sling?
The below images tells us how a URL is resolved and mapped to a resource.
Consider the URL
GET – www.mywebsite.com/products/product1.printable.a4.html/a/b?x=12
Here the type of request will be HTTP GET request
We can break it down into its composite parts:
Sling's Request Processing Revisited
In Apache Sling each
(http) request is mapped onto a JCR resource, i.e. a repository node.
This is very different from other web frameworks you might be familiar
with, say, Struts or Rails.
In these frameworks a request is mapped onto a controller, i.e. a url
really addresses application code, so the application developer usually
implements some application logic that retrieves model data and passes
it on to the view.
Just like Rails or Struts, Sling implements a model-view-controller architecture.
However, in Sling a request addresses a piece of content. The mapping
between request and model (data, content) is accomplished through the
url so there is no need for further custom mapping logic.
Node selection
So, how does this work in detail? Consider an http GET request for the url:
/content/corporate/jobs/developer.html
First,
Sling will look in the repository for a file located at exactly this
location. If such a file is found, it will be streamed into the response
as is. This behavior allows you to use Sling as a web server and store
your web application's binary data in the repository as well.
However, if there is no file to be found Sling will look for a repository node located at:
/content/corporate/jobs/developer
(i.e. it drops the file extension). If this node cannot be found Sling will return the http code 404.
Script folders
The scripts
that Sling uses to process http requests are stored in subfolders of
"/apps". Those subfolders are usually of type nt:folder, but that's not a
requirement.
Script selection
Nodes can have a special property named "sling:resourceType" that determines the resource type.
Let us consider the simplest case (using the example request URL from
above) and assume that the resource type is, say, "hr/job". The selected
script will then be "/apps/hr/job/job.esp" (the last part of the
resource type will have to be the file name). This works for GET
requests and URLs ending in ".html".
Requests
using other request methods, say POST, will cause Sling to look for the
script at "/apps/hr/job/job.POST.esp". Request URLs ending in something
else than ".html", say ".pdf", will make Sling look at
"/apps/hr/job/job.pdf.esp". The convention to distinguish the two cases
is that http methods are all uppercase and the extension of the request
is all lowercase.
In a
content-centric application the same content (aka nodes) must often be
displayed in different variations, e.g. as a teaser view and as a detail
view. In Sling this is achieved through selectors. The selector is specified in the URL like e.g.
/content/corporate/jobs/developer.detail.html
For this URL Sling would locate the script at "/apps/hr/job/job.detail.esp"
If the selected resource has no special resource type a
script will be looked up based on the content path. For example, the
script for /content/corporate/jobs.html will be searched in
/apps/corporate.
Script engine
The ".esp"
extension of the scripts used in the examples above indicates script
engine to use. ".esp" stands for Ecma script and internally uses Rhino,
Mozilla's Javascript engine. Other supported extensions are ".rb" for JRuby scripts, ".jsp" for JSPs or ".jst" for client-side execution (".jst" denotes Javascript template).
Some interesting special cases
The
examples above describe rendering nodes as html or as a pdf. Howevere,
there are also some built-in renderers for json and txt. The
corresponding node presentations are located at (using the example form
above):
/content/corporate/jobs/developer.json
and
/content/corporate/jobs/developer.txt
respectively.
For http
error handling (404 or 500) Sling will look for a script at
"/apps/sling/servlet/errorhandler/404.esp" and 500.esp, respectively.
More on script selection
If you need to find out more on the details of script selection in Sling have a look at Sling ticket 387 where developer Felix Meschberger a lot more on the script resolution process.
SLING 387:
Simplify script paths and names
According
to the findings in the dev list thread "Simplifying script paths and
names?" at [1] I would now like to propose the implementation of this
change in script/servlet path resolution:
Note: This
issue talks about scripts. But as servlets are mirrored into the virtual
Resource Tree accessible through the ResourceResolver, servlets are
treated exactly the same as scripts (or vice-versa actually). So the
discussion applies to servlets as well as to scripts.
(1) Script Location
Scripts to handle the processing or a resource are looked up in a single location:
{scriptPathPrefix}/{resourceTypePath}
Where
{scriptPathPrefix} is an absolute path prefix (as per
ResourceResolver.getSearchPath()) to get absolute paths and
{resourceTypePath} is the resource type converted to a path. If the
{resourceTypePath} is actually an absolute path, the {scriptPathPrefix}
is not used.
Example:
Given the search path [ "/apps", "/libs" ] and a resource type of
sling:sample, the following locations will be searched for scripts:
* /aps/sling/script
* /libs/sling/script
(2) Within the location(s) found through above mechanism a script is searched whose script name matches the pattern
{resourceTypeLabel}.{selectorString}.{requestMethod}.{requestExtension}.{scriptExtension}
where the fields have the following meaning:
{resourceTypeLabel} - the last segment of the {resourceTypePath} (see above)
This part is required. Only scripts whose name starts with this name are considerd
{selectorString} - the selector string as per RequestPathInfo.getSelectorString
This part is optional. The more selectors of the selector string match, the
better.
{requestMethod}
The request method name. This is optional for GET or HEAD requests
and is required for non-GET/non-HEAD requests
{requestExtension}
The extension of the request. This is optional.
{scriptExtension}
The extension indicating the script language. Not used for selecting
the script but for selecting the ScriptEngine. This is of course not existing
for servlets.
If multiple
scripts would apply for a given request, the script with the best match
is selected. Generally speaking a match is better if it is more
specific. More in detail, a match with more selector matches is better
than a match with less selector matches, regardless of any request
extension or method name match.
For
example, consider a request to resource /foo/bar.print.a4.html of type
sling:sample. Assuming we have the following list of scripts in the
correct location:
(1) sample.esp
(2) sample.GET.esp
(3) sample.GET.html.esp
(4) sample.html.esp
(5) sample.print.esp
(6) sample.print.a4.esp
(7) sample.print.html.esp
(8) sample.print.GET.html.esp
(9) sample.print.a4.html.esp
(10) sample.print.a4.GET.html.esp
It would
probably be (10) - (9) - (6) - (8) - (7) - (5) - (3) - (4) - (2) - (1).
Note that (6) is a better match than (8) because it matches more
selectors even though (8) has a method name and extension match where
(6) does not.
If there is
a catch, e.g. between print.esp and print.jsp, the first script in the
listing would be selected (of course, there should not be a catch...)
1. Update Servlet Resolution Description Resolved
To be
clear: This new mechanism replaces the script resolution mechanism of
today. As such this change is not backwards compatible and existing
applications will have to be adapted.
Bertrand Delacretaz added a comment - 18/Apr/08 13:41
> Given the search path [ "/apps", "/libs" ] and a resource type of sling:sample, the following locations will be
> searched for scripts:
> * /aps/sling/script
> * /libs/sling/script
I think this should be
/apps/sling/sample
/lib/sling/sample
And I'm not sure what the initial */ means in your example, I thought the search paths were absolute.
Felix Meschberger added a comment - 18/Apr/08 13:53
the initial "*" in the lines is just a numbering symbol. It has no code significance. And yes, your fixes are correct.
David Nuescheler added a comment - 25/Apr/08 15:38
i think it is important that this change was originally suggested to
make the simple cases as simple and intuitive as possible for
the user of sling and not to come up with something that is really
easy and consistent to map for the sling implementation.
let me try to explain with an example:
as a user
of sling i would like to have my app in /apps/myapp and lets say i have a
node of resourceType "myapp/homepage" at "/content/myapp".
i would like to to be able to structure my applications as follows:
(1) /apps/myapp/homepage/hompage.esp (or html.esp or GET.esp)
(2) /apps/myapp/homepage/edit.esp (or edit.html.esp)
(3) /apps/myapp/homepage/header/highlight.jpg.esp
(4) /apps/myapp/homepage/header/selected.jpg.esp
(5) /apps/myapp/homepage/header/small.jpg.esp
where
/content/myapp.html -> (1)
/content/myapp.edit.html -> (2)
/content/myapp.header.highlight.jpg -> (3)
/content/myapp.header.selected.jpg -> (4)
/content/myapp.header.small.jpg -> (5)
i think it is important that we avoid unnecessary repetition at any point
and we would allow for enough flexibility in the /apps directory allow
the user to come up with something short, distinct and meaningful.
I haven't
found out how to hook a script to POST with a "delete" selector, tried
POST.delete.html.esp and various other options but that didn't work.
Looking at the code, I think that might not work at all, and I didn't find tests related to this.
The correct script path would be .../delete/POST.esp
Request
Selectors are ignored for non-GET/HEAD requests. Hence the POST-related
test is expected to fail. This is related to issue (III) in [1] stating
that not all request methods are equal.
Hence, I
suggest to for the moment comment out these tests with a comment stating
this situation and not implementing that support. Reason for this is,
that a resource URL should address the resource (and at most give some
hint for a specific representation, such as html or txt) but not include
an operation such as delete.
* Refactored resolution of error handler servlets/scripts to use new mechanism
* Removed unused methods and classes
* Renamed helper classes to reflect their functionality
Closing this issue for now. Errors in the new implementation should be reported in new issues.
Currently, working with selectors requires you to put scripts in
subfolders, for example
/apps/foo/html.esp
/apps/foo/someselector/html.esp
and worse, all GET scripts which produce html are named html.esp,
which can be confusing when editing them.
We talked about this with David and Felix, here's a proposal for
simplifying those names in the "happy case", while keeping the current
conventions to resolve potential name conflicts where needed. Comments
welcome.
= Proposal =
The following variants should be accepted for script names, examples:
a) sling:resourceType=foo, request = bar.html
Sling searches for the following scripts and uses the first one found:
/apps/foo/html.esp
/apps/foo/foo.esp
The only change is that the script used for html rendering can
optionally be named foo.esp, to avoid having many scripts called
"html.esp" which is not practical when opening many of them in an
editor or IDE.
a) sling:resourceType=foo, request = bar.selector.html
The following scripts can be used to process this request, the first
one found being used:
/apps/foo/selector/html.esp
/apps/foo/selector.html.esp (same but with dots instead a subfolder)
/apps/foo/selector.esp
/apps/foo/html.esp (not specific to the selector)
/apps/foo/foo.esp (not specific either)
In the "happy case" people would then just have those two scripts to
handle the above cases:
/apps/foo/foo.esp
/apps/foo/selector.esp
Protocol host content path selector(s) extension suffix param(s)
http://myhost:products/product1.printable.a4.html/a/b?x=12
7. What is OSGi? What is the benefit of OSGi? What is Felix?
OSGi is a framework which allows modular development of applications using java.
A large
application can be constructed using small reusable components(called
bundles in terms of OSGi) each of which can be independently started,
stopped, and also can be configured dynamically while running without
requiring a restart.
Consider a
scenario where you have a large application which uses a logging
framework. This logging framework can be deployed as an OSGi Bundle,
which can be managed independently. Therefore, it can be started when
required by our application and can be stopped when not in use. Also the
OSGi container makes these bundles available as services, which can be
subsribed by other parts of application.
The main advantages of using OSGi :
1) reduces the complexity of the system.
2) Makes the components loosely couples and easy to manage.
3) Increases the performance of the system, since parts of application which are not in use,need not to be loaded in the memory(although there is not a drastic change in performance and also some people argue that running an OSGi container itself takes huge memory).
2) Makes the components loosely couples and easy to manage.
3) Increases the performance of the system, since parts of application which are not in use,need not to be loaded in the memory(although there is not a drastic change in performance and also some people argue that running an OSGi container itself takes huge memory).
The OSGi
Framework is made up of three layers -- Module, Lifecycle, and Services
-- that define how extensible applications are built and deployed. The
responsibilities of the layers are:
Module --- Defines how a module, or a Bundle in
OSGi-speak, is defined. Basically, a bundle is just a plain old JAR
file, whose manifest file has some defined entries. These entries
identify the bundle with a symbolic name, a version and more. In
addition there are headers which define what a bundle provides
Export-Package and what a bundle requires to be operative Import-Package
and Require-Bundle.
Lifecycle ---
The lifecycle layer defines the states a bundle may be in and describes
the state changes. By providing a class, which implements the
BundleActivator interface and which is named in the Bundle-Activator
manifest header, a bundle may hook into the lifecycle process when the
bundle is started and stopped.
Services ---
For the application to be able to interact, the OSGi Core Specification
defines the service layer. This describes a registry for services,
which may be shared.
8. What are templates ?
A Template
is used to create a Page and defines which components can be used within
the selected scope. A template is a hierarchy of nodes that has the
same structure as the page to be created, but without any actual
content.
Each Template will present you with a selection of components available for use.
• Templates are built up of Components;
• Components use, and allow access to, Widgets and these are used to render the Content.
- If you want your template to be displayed in the Create Page dialog when creating a page right under Websites from the Websites console, set the allowedPaths property of the template node to: /content(/.*)?
Templates
are used to create Pages of type cq:Page (as mentioned earlier, a Page
is a special type of Component). Each CQ Page has a structured node
jcr:content. This:
• is of type cq:PageContent
• is a structured node-type holding a defined content-definition
• has a property sling:resourceType to reference the component holding the sling scripts used for rendering the content
9. What is Dispatcher ?What is the role of Dispatcher in CQ5?
The
Dispatcher is the Adobe caching and/or load balancing tool that helps
realize a fast and dynamic Web authoring environment. For caching, the
Dispatcher works as part of an HTTP server, such as Apache, with the aim
of storing (or "caching") as much of the static website content as
possible and accessing the website's layout engine as infrequently as
possible. In a load balancing role, the Dispatcher distributes user
requests (load) across different clustered CQ instances (renders).
For
caching, the Dispatcher module uses the Web server's ability to serve
static content. The Dispatcher places the cached documents in the
document root of the Web server.
Dispatcher is a CQ5 tool for caching and load-balancing. It has 2 responsibilities.
1)
Caching – To cache as much content as possible, so that it doesn't need
to access layout engine frequently for generating content dynamically.
2) Load-balancing – To increase the performance by load-balancing.
Dispatcher uses 2 main strategies for caching.
1) Cache as much content as possible as static pages.
2) Accessing layout engine as little as possible.
2) Accessing layout engine as little as possible.
Note : The
Dispatcher uses a Cache Directory for caching static content. The cached
documents are created in the root of a web-server.
· How does the Dispatcher perform caching?
The
Dispatcher uses the web server's ability to serve static content. The
Dispatcher stores cached documents in the web server’s document root.
The Dispatcher has two primary methods for updating the cache content
when changes are made to the website.
ñContent Updates remove the pages that have changed, as well as files that are directly associated with them.
ñAuto-Invalidation
automatically invalidates those parts of the cache that may be out of
date after an update. For example, it effectively flags relevant pages
as being out of date, without deleting anything.
· How does CQ perform load balancing?
Load
Balancing distributes user requests (load) across different clustered
CQ instances.The following list describes the advantages for load
balancing:
ñIn
practice this means that the Dispatcher shares document requests
between several instances of CQ. Because each instance has fewer
documents to process, you have faster response times. The Dispatcher
keeps internal statistics for each document category, so it can estimate
the load and distribute the queries efficiently.
ñIf
the Dispatcher does not receive responses from an instance, it will
automatically relay requests to one of the other instance(s). Thus, if
an instance becomes unavailable, the only effect is a slowdown of the
site, proportionate to the computational power lost.
ñwhen
a user session is established, then all incoming requests from that
user should be served by the same cq instance, because other cq
instances cannot recognize the user session and generate personalized
pages for him. Dispatcher makes sure all requests for user session are
served from the same cq instance.
10. What is Replication? How is Content Moved from author to publish instance?What is Activation?
The content once published is moved from author instance to publish instance using replication agent.
Replication agent has following responsibilities:
ñMove content from author to publish instance.
ñIf
any content is updated, then it flushes the older content from
dispatcher cache, but it won't put new content at the same time. New
content will be fetched into cache, when the next time it is requested.
A
development environment can contain multiple cq-author and multiple
cq-publish instances, therefore an author instance can be configured to
have many replication agents. Each of which will replicate the content
in 1 or more publish instances.
When
a request is made from user to publish any content, then the
replication agent packages the content and places it in a replication
queue.
A Listener servlet in publish instance receives the content package and updates the content in publish instance. The default listener servlet in publish instance is “http://localhost:4503/bin/recieve” .
11. How is content moved from publish instance to author instance?What is Reverse Replication?
Consider
the scenario where your website is having a blog or a forum, and the
users are posting comments in the blog. Then that comments will only be
in publish instance. The content is moved from publish instance to
author instance using reverse replication and the job is done by reverse
replication agent.
The reverse
replication agent places any content updates in an outbox configured in
publish instance. The replication listeners in author environment keep
listening to the publish outbox and whenever any content is placed in
publish outbox, the listeners update the content in author instance.
12. What is persistence manager in cq5?
CQ uses persistence manager to save the content to a persistent storage like file system or a database.
By default
the crx content is stored using Tar Persistence manager. It stores the
content to file-system in standard linux archive files called tar.
if you want to store the repository content in a database, then you can configure cq5 to use a database persistence manager.
13. What is New in CQ 5.5 ?
ñCreative Suite: Adobe’s
flagship software now integrates seamlessly with CQ5.5’s Digital Asset
Management (DAM) via Drive or Bridge. Creative teams can now adjust a
photo, push it directly to the web, and then get analytic feedback on
how photo versions are performing—all without ever leaving Creative
Suite. The move allows Adobe to start interesting WCM conversations with
every company that uses Adobe’s Creative Suite. And last I checked,
that was every company on the planet.
ñScene7: At
first this cloud-based digital asset management system was awkwardly
competitive with CQ5’s own DAM, and even Adobe seemed unclear when they
should suggest a given product to customers. But the integration has
made it much easier for companies in retail, hospitality, travel, or CPG
to take advantage of Scene7’s dynamic personalization capabilities.
ñSiteCatalyst and Test&Target: While
the new version of the integration with these two former Omniture
products doesn’t appear to add much new functionality from the CQ5.4
iteration, the presentation layer is much more intuitive and plays very
nicely with the personalization features.
ñeCommerce Capabilities: WCM
and eCommerce platforms have become more competitive in recent years.
WCM systems often claim to handle product catalogues seamlessly and
eCommerce software makes the same flawed case about handling complex
digital marketing messaging. Adobe seems to have recognized that the
market demands a unified approach, so they’ve partnered with hybris
software to add some nice eCommerce capabilities just in their
out-of-the-box demo site. Of course, if you want to use these features
on your site, there are additional licensing costs.
ñMobile: CQ5.4
already had a sophisticated mobile Web solution; CQ5.5 adds the ability
for content authors to work directly on mobile apps. After Adobe’s
PhoneGap acquisition, adding this functionality was clearly on Adobe’s
roadmap, but to incorporate the integration in the first
post-acquisition release is impressive.
ñUndo/Redo: Ok,
admittedly, multi-step undo/redo with control-Z and control-Y isn’t
really a theme, but you’ve got to give this feature its due. This is
super-cool Web tech for the geeks, got-to-have-it-now sexiness for CQ5
demonstrators, and the savior from careless keystrokes for countless
grateful content authors.
ñThe Page Exporter
CQ allows you to export a page as a complete web page including images, .js and .css files.
ñUsing a Proxy to Integrate with InDesign Server
INDESIGN
This allows you design page layouts for print and/or digital distribution.
This allows you design page layouts for print and/or digital distribution.
INDESIGN SERVER
This engine enables you to programmatically create automated documents based on what you have created with InDesign. It operates as a service offering an interface to its ExtendScript engine.
The scripts are written in extendscript, which is similar to javascript.
This engine enables you to programmatically create automated documents based on what you have created with InDesign. It operates as a service offering an interface to its ExtendScript engine.
The scripts are written in extendscript, which is similar to javascript.
CQ DAM PROXIES
A
proxy is used to enable the two-way communication between a CQ
instance(s) and a proxy worker (for example, for communicating with an
InDesign Server). Any CQ instance can be used as a proxy and can
communicate with any number of other CQ instances.
PROXY WORKER
A
proxy worker is a processor responsible for handling a job and creating
a result. A proxy worker can be used for a wide variety of tasks, for
example using an InDesign Server to process files.
What is the difference between 1. <c:import url="layout-link.jsp" /> 2. <sling:include path="layout-link.jsp" /> 3. <cq:include script="layout-link.jsp" />What is the advantage of each tag? When should each be used?
CQ Include is most appropriate when you are doing standard component/template development.
Sling include is most appropriate when you are trying to include a piece of content as based strictly on sling resource resolution and not CQ component type logic.
Sling include is most appropriate when you are trying to include a piece of content as based strictly on sling resource resolution and not CQ component type logic.
1. <c:import url="layout-link.jsp" />
I
assume this is the import tag of the Standard Tag Library. This tag is
documented
athttp://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/import.html and
does not know about Sling directly.
But
-- asuming -- this tag is using a RequestDispatcher to dispatch the
request, this tag will also pass Sling and the Sling resource resolver.
2. <sling:include path="layout-link.jsp" />
This is the include tag of the Sling JSP Tag library. This tag knows about Sling and also supportsRequestDispatcherOptions.
3. <cq:include script="layout-link.jsp" />
This
tag is Communiqué specific extension of the Sling JSP Tag library
include tag. IIRC it supports callings scripts in addition to just
including renderings of resources.
What is the advantage of each tag? When should each be used?
In
a Communiqué application, I would suggest to generally use the
Communiqué or Sling include tag since this provides you more Sling
support.
You
may use the JSTL import tag if you don't have specific requirements for
Sling extended features, plan to use the JSP (fragment) outside of
Communiqué or if you want to further process the generated (imported)
content with a reader or a variable.
In
the future, it is conceivable that the Sling and/or Communique tag
library will also provide an import tag similar to the JSTL import tag
to be able to further process the imported result.
15. What are Clientlibs?
Clientlib: CQ Static Resource Management
In
this post I am going to cover a feature that is provided in CQ to
manage static resources (js, css, images etc.). For every web
application performance is an important factor that we usually ignore at
first place and down the line it becomes a bottleneck for us. So,
performance can be improved by considering various factors while
designing a new application, few of them are listed below:
1) Web page sizeA web page is composed of HTML markup, JS files, CSS files and images. We should try to keep page size as low as possible so that page is loaded quickly in browser.
2) Ajax calls v/s full page reload
There are many instances where it’s always better to make an Ajax call to hit the server and update a small area (HTML DOM) of page rather than reloading whole page.
3) Amount of data transfer between server and browser
When we make a call to service on server, the services should only return page/context specific data rather returning whole information/data. We can call server again (via Ajax calls) to fetch limited data and update page accordingly.
In this post I’ll try to show the benefit of using client libs feature to reduce the page size. Let’s consider a scenario where we have a web application built using CQ and it has multiple pages that are composed of many component. Each component needs a set of JS, CSS and images which might not be needed on other pages so, it does not make sense to load all those irrelevant resources on other pages where that component is not present.
For example we have a login page and a home page that user sees after successful login. The login page is composed of a login component (with a form) to enter username and password and we are using a jQuery validation plugin to validate form before submitting it to server. Once user is validated we redirect user to home page which does not have any form (i.e. we don’t need validation jQuery
plugin) on this page and there is no point in including validation plugin and we only need jQuery javascript file.
Login Page: needs jQuery and jQuery Validation plugin
Home Page: needs just jQuery
Normally, we include resource (like JS, CSS) in section of a page (in CQ it’s a template). If jQuery and jQuery validation plugin is included in head section of template then it’ll be included on every page no matters whether that page actually needs them or not and hence the page size is increased unnecessarily. There is better way to handle this in CQ and load the resources when they are actually needed and this is where CQ’s clientlib feature comes in to play.
What is client lib feature?
With client lib feature we can categorize every JS and CSS file as a library (with a specific name) and can include/import them in individual component or template (if it is used globally). For the time being consider this as java import feature. If on a page there are multiple component that needs the same library then CQ will make sure that the library is loaded only once. We can also define dependencies while creating clientlibs, e.g. jQuery validation plugin is dependent on base jQuery JS file.
How to define a client lib in CQ?
To define a client lib CQ follow below steps:
1) create a folder called clientlibs (by right clicking on designs folder) under /etc/designs (actually we can create this folder anywhere we want but, to keep it simple and consistent I am creating this under designs folder)
1) Web page sizeA web page is composed of HTML markup, JS files, CSS files and images. We should try to keep page size as low as possible so that page is loaded quickly in browser.
2) Ajax calls v/s full page reload
There are many instances where it’s always better to make an Ajax call to hit the server and update a small area (HTML DOM) of page rather than reloading whole page.
3) Amount of data transfer between server and browser
When we make a call to service on server, the services should only return page/context specific data rather returning whole information/data. We can call server again (via Ajax calls) to fetch limited data and update page accordingly.
In this post I’ll try to show the benefit of using client libs feature to reduce the page size. Let’s consider a scenario where we have a web application built using CQ and it has multiple pages that are composed of many component. Each component needs a set of JS, CSS and images which might not be needed on other pages so, it does not make sense to load all those irrelevant resources on other pages where that component is not present.
For example we have a login page and a home page that user sees after successful login. The login page is composed of a login component (with a form) to enter username and password and we are using a jQuery validation plugin to validate form before submitting it to server. Once user is validated we redirect user to home page which does not have any form (i.e. we don’t need validation jQuery
plugin) on this page and there is no point in including validation plugin and we only need jQuery javascript file.
Login Page: needs jQuery and jQuery Validation plugin
Home Page: needs just jQuery
Normally, we include resource (like JS, CSS) in section of a page (in CQ it’s a template). If jQuery and jQuery validation plugin is included in head section of template then it’ll be included on every page no matters whether that page actually needs them or not and hence the page size is increased unnecessarily. There is better way to handle this in CQ and load the resources when they are actually needed and this is where CQ’s clientlib feature comes in to play.
What is client lib feature?
With client lib feature we can categorize every JS and CSS file as a library (with a specific name) and can include/import them in individual component or template (if it is used globally). For the time being consider this as java import feature. If on a page there are multiple component that needs the same library then CQ will make sure that the library is loaded only once. We can also define dependencies while creating clientlibs, e.g. jQuery validation plugin is dependent on base jQuery JS file.
How to define a client lib in CQ?
To define a client lib CQ follow below steps:
1) create a folder called clientlibs (by right clicking on designs folder) under /etc/designs (actually we can create this folder anywhere we want but, to keep it simple and consistent I am creating this under designs folder)
2) Create a new node under clientlibs folder called as jqvalidate with type as cq:ClientLibraryFolder (as shown below):
3) Copy/Put your JS (jq.validate-min-XXX.js) file in jqvalidate folder (we can also copy and css file to this folder if there is any).
4) Create a file js.txt in jqvalidate folder (also create another file css.txt if you have copied any css file in jqvalidate folder).
5) Add name of JS file (e.g. jq.validate-min-XXX.js) in js.txt (also add name of CSS file in css.txt) file and save it.
6) Click on jqvalidate folder node in crxde and open the Properties tab and update/add 2 new properties as shown below and save the node:
NOTE: both properties are of type String Array (String[])
a) categories: This is the name using which we’ll be referencing our jQuery validation client lib in our components and templates.
b) dependencies: Using this property we define the dependency of current library (in this case jQuery validation) on another client lib (in this case cq.jquery).
At this point we are done with creation of a validation library now, we’ll see how to use for developing components and templates.
How to use/import client lib?
To include a client lib in your component/template simply add following code/tag:
1. <cq:includeclientlib categories="jquery.validate">
2. </cq:includeclientlib>
If you want to load multiple client libs then provide comma separated names against categories attribute in above tag e.g.
1. <cq:includeclientlib categories="jquery.validate, someother.clientlib">
2. </cq:includeclientlib>
The
"clientlib" functionality will manage all your Javascript and CSS
resources in your application. It takes cares of dependency management,
merging files and minifying content.
16. What is the difference between design dialog and a normal dialog?
A design dialog is used to globally store variables through the template properties’ whereas a normal dialog stores all variables inside the page’s properties. One of the major benefits of using the design dialog is that if you have a hundred pages sharing the same template the variables will be shared amongst them. Also, note that you can have both design dialog and normal dialog on a page.
A
dialog saves content relative to the given page. In comparison, a
'design' dialog saves content globally (at a template level).
Within CQ/AEM, there are some key folder structures. For example, you may have a page at the following path:
/content/your-site/en_HK/your-page
Within
that page you have a component that has both a dialog and a design
dialog. When you save content in the dialog, it is saved to a node
beneath the given page. Something like:
/content/your-site/en_HK/your-page/jcr_content/some-par-sys/your-component
However, when you save content to the design dialog, it is saved to a 'global' design path. Something like:
/etc/design/your-site/en_HK/your-template/jcr_content/your-component
This mechanism allows the content that has been saved in the design dialog for the GIVEN TEMPLATE to be available in all templates of the same type (basically).
This mechanism allows the content that has been saved in the design dialog for the GIVEN TEMPLATE to be available in all templates of the same type (basically).
This can come in handy with headers, footers, and (as the name implies) in cases where a consistent design should be used
17. What is Personalization?
Personalization provides your users with a customized environment that displays dynamic content selected according to their specific needs.
There is an ever-increasing volume of content available today, be it on internet, extranet, or intranet websites.
Personalization
centers on providing the user with a tailor-made environment displaying
dynamic content that is selected according to their specific needs; be
this on the basis of predefined profiles, user selection, or interactive
user behavior.
Teaser Component used in Personalization and Segmentation also.
18. What is a CQ5 overlay/override component?
I've
been asked to create a CQ5 "overlay" component by simply copying the
out-of-box component from /libs/foundation/components/flash to
/apps/myproject/components/flash. My question is: what happens to the
original - is it just ignored?
Overlay /override component is Universally across the WEM.
Use
of the Overlay component is , when you want to use the out-of-box
component and you want to add some extra feature in it , so instead of
changing the code from “libs/foundation/components/component-name.jsp”
just follow the below process and use it. By using this we can use the
out-of-box feature with our extra feature without changing behaviour of
out-of-box component . So that other projects which are using it can't
be affected.
Example : Overlaying the TEXT component.
- Create the “foundation/components” folder under apps as in figure 1.
- Copy the text component from “libs/foundation/components/text” to above path.
- Append the below code in text.jsp
- Change the jcr:title to Text Overlayed.
<div style="border-width:1px;border-style:solid;border-color:black;width:100%;background:grey;color:white">
Overlaid text component
</div>
|
Figure 1 : create the foundation/components folder under apps.
- Now open the “http://localhost:7502/cf#/content/geometrixx/en.html” page, you will see the
“apps/foundation/components/text” instead of “libs/foundation/components/text”
6. This
will CHANGE how the foundation component behaves in all instances. And
the existing sidekick component remains, but behaves differently.
It
is not ignored. Both components can show up in the authors' sidekick --
one will say flash (foundation), the other flash (myproject). When one
of these is used by an author CQ will instantiate appropriately. The
usual rules apply for what shows up in the sidekick (group name,
selected in design mode, etc.)
a CQ5 "overlay" leverages sling rules for resource resolving.
if/libs/foundation/components/flash needs
an overlay, you "overlay" the corresponding file at
location /apps/foundation/components/flash/filename This will CHANGE how
the foundation component behaves in all instances. And the existing
sidekick component remains, but behaves differently.
If
you have a NEW component at /apps/myproject/components/flash, it can
inherit from the foundation component via sling:resourceSuperType on the
new component. In that case, you have a new component in the sidekick.
In your new component, you could use the same values
forjcr:title, componentGroup, or you could change them to distinguish
your component in the sidekick. If the title, componentGroups are the
same, the sidekick can distinguish them with parenthesis around the
webapp (foundation) vs (myproject). However, I have seen situations
where it is impossible as an author to distinguish them.
19. How to extend/inherit/Enhance the components ?
Difference between the Overlay components and Extended Components is -
Overlay/Overrided Component
|
Extended/Inherited Components
|
1. Universally available across the WEM.
|
1.Not universally available across WEM as they are inherited for specific project.
|
2. They are copied from “/libs/foundation/components/ ” to “/apps/foundation/components/”
|
2. They are extended by using
“ sling:resourceSuperType ” property
|
Example 1 : Extending the text component.
1. Create the project under apps folder. As in figure.
2.
3. Open “newtext.jsp” add the below code in it
<%--
New Text Component component.
--%><%
%><%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %><%
%><div style="border-width:1px;border-style:solid;border-color:black;width:100%;background:red;color:white">
Inherited text component
</div>
<%
%><cq:text property="text"/>
|
EXAMPLE 2 :
Figure 1 : page component is using sling:resourceSuperType :foundation/components/page
Figure 2 : blog component is using sling:resourceSuperType – Test/components/page
3. Test/page/body.jsp
<%@ include file="/libs/foundation/global.jsp" %>
<div><cq:include script="header.jsp"/></div>
<div><cq:include script="content.jsp"/></div>
<div><cq:include script="footer.jsp"/></div>
|
4. Test/page/content.jsp
<%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %>
<h1> Base content <h1>
|
5. Test/page/footer.jsp
<%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %>
This is the Footer
|
6. Test/page/header.jsp
<%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %>
This is Header
<cq:include path="header" resourceType="foundation/components/iparsys"/>
|
6. Test/blog/content.jsp
<%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false" %>
<h1>Blog Content</h1>
|
If
you have a NEW component at /apps/myproject/components/flash, it can
inherit from the foundation component via sling:resourceSuperType on the
new component. In that case, you have a new component in the sidekick.
In your new component, you could use the same values for
jcr:title, componentGroup, or you could change them to distinguish your
component in the sidekick. If the title, componentGroups are the same,
the sidekick can distinguish them with parenthesis around the webapp
(foundation) vs (myproject). However, I have seen situations where it is
impossible as an author to distinguish them.
20. Difference between Parbase and parsys?
Parbase
|
Parsys
|
Parbase
is a key component as it allows components to inherit attributes from
other components, similar to subclasses in object oriented languages
such as Java, C++, and so on. For example, when you open
the/libs/foundation/components/text node in the CRXDE Lite, you see that
it has a property named sling:resourceSuperType, which
references the parbase component. The parbase here defines tree scripts
to render images, titles, and so on, so that all components subclassed
from this parbase can use this script.
Also for image component : crop,map etc inheritd
Users do not need access to the parbase.
|
The
paragraph system (parsys) is a compound component that allows authors
to add components of different types to a page and contains all other
paragraph components. Each paragraph type is represented as a component.
The paragraph system itself is also a component, which contains the
other paragraph components.
|
21. Difference between Parsys and Iparsys?
Parsys
|
iParsys
|
Parsys
is a placeholder where we can drag and drop the component and the
script (or content) inside the component will be rendered to that place.
|
Iparsys
or Inherited Paragraph System is similar to parsys except it allows you
to inherit the created paragraphs from the parent.
Cancel Inheritance : For Child cancel
Disable Inheritance: From parent Disable
|
22. “What benefit does an OSGi Bundle provide over a conventional Java “jar” file?”
While it is true that you can start and stop a “jar” file, the concept of a bundle expands upon the conventional “jar” file by including metadata such as the version and list of services imported and exported by the bundle. This allows an OSGi bundle to be installed, updated, and uninstalled without taking down the entire application. Also, OSGi bundling allows multiple versions to exist, with the OSGi framework assuming the responsibility of matching “service consumers” with “service providers”. The net result is that an OSGi bundle is more of a standalone “software module” than a “jar”, “war”, or “ear” file.
If
you build web applications with Apache Sling or CRX Quickstart you
might want to extend the core functionality, e.g. for starting a
background process or connecting to some legacy system.
Fortunately,
this is easy as Sling is based on OSGi. OSGi (Open Services Gateway
Initiative) defines an architecture for developing and deploying modular
applications and libraries. As such, extending Sling with
application-specific components ("bundles" as they are called in OSGi
lingo) essentially means creating a bundle. In this post I will walk you
through the complete process. All code and configuration is attached to
this post as a deployable bundle.
One
disclaimer before we start, though: if have no clue at all about OSGi
you should get some basic understanding from TheServerSide,
or JavaWorld (the TSS article uses the terms "repository" and "node" in a
generic way, not for JCR repositories and nodes as in this post).
Once you have a basic notion what a bundle is you're good to go.
23. Create a OSGi bundle?How will you expose the Bundle/Service?
A
bundle is a jar file plus some meta information. Let us start with a
simple service interface class. In OSGi development it is common
practice to use interfaces and implementing classes.
package com.day.samples;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
public interface HelloService {
public String sayHello();
public String getReversedNodePath(Node
node) throws RepositoryException;
public String getRepository();
public void log(String text);
}
This
is really just a plain old Java interface, nothing OSGi- or
Sling-specific to be seen here, just some JCR classes are imported. I
chose these four methods because they provide some insights how to
develop OSGi bundles on top of Sling. However, they are not "required"
in the sense that e.g. EJB 2 would require a certain structure of your
classes. The implementing class looks like:
package com.day.samples.impl;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.sling.jcr.api.SlingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.samples.HelloService;
public class HelloServiceImpl implements
HelloService{
private SlingRepository repository;
private static final Logger log =
LoggerFactory.getLogger(HelloServiceImpl.class);
public String sayHello() {
return ("Hello World!!");
}
public String getReversedNodePath(Node node)
throws RepositoryException {
return new
StringBuffer(node.getPath()).reverse().
toString();
}
public String getRepository() {
return
repository.getDescriptor(
SlingRepository.REP_NAME_DESC);
}
protected void bindRepository(SlingRepository
repository) {
this.repository = repository;
}
protected void unbindRepository(SlingRepository
repository) {
this.repository = null;
}
public void log(String text) {
log.error(text);
}
}
The
implementation imports the SlingRepository class and a logger class
that comes with Sling. In order to compile this class you will need to
have the Sling jars on your classpath. If you use CRX Quickstart find
them in launchpad/felix/bundleXX.
For the bundle description we will need a descriptor file called MANIFEST.MF located in META-INF and contains:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: HelloWorld Plug-in
Bundle-SymbolicName: HelloWorld
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework;version="1.3.0",
org.apache.sling.jcr.api,org.slf4j
Export-Package: com.day.samples;version="1.0.0"
Private-Package: com.day.samples.impl
Service-Component: OSGI-INF/serviceComponents.xml
Note
that the packages that are used in the implementing class above must be
imported. Also, the packages that shall be exposed from our bundle to
other bundles must be marked as "exported". Further, there must be a reference to the second needed descriptor file OSGI-INF/serviceComponents.xml. This file contains:
<?xml version="1.0" encoding="UTF-8"?>
<components
xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
<scr:component enabled="true" immediate="true"
name="com.day.samples.impl.HelloServiceImpl">
<scr:implementation
class="com.day.samples.impl.HelloServiceImpl"/>
<scr:service servicefactory="false">
<scr:provide
interface="com.day.samples.HelloService"/>
</scr:service>
<scr:property name="service.description"
value="Say hello sample service"/>
<scr:property name="service.vendor"
value="Day"/>
<scr:property name="service.pid"
value="com.day.samples.impl.HelloServiceImpl"/>
<scr:reference name="repository"
interface="org.apache.sling.jcr.api.
SlingRepository"
cardinality="1..1" policy="static"
bind="bindRepository"
unbind="unbindRepository"/>
</scr:component>
</components>
This
file configures which implementation of the interface shall be used. It
also configures the "injection" of the repository variable into the
HelloServiceImpl class (highlighted). The "setter" is configured in the
"bind" attribute. HelloServiceImpl must implement this method.
For
creating an OSGi bundle you just need to compile these classes and
package them in a jar file together with the descriptors (the complete
bundle is attached).
The Sling/Felix console
The
Sling console is a web application that comes with Sling and CRX
Quickstart that allows you (among other things) to deploy new bundles.
It is located at http://localhost:7402/system/console/list. Bundle
details can be seen by clicking on a bundle name. This reveals e.g. the
bundle version and the exported packages. For example, note that the
org.slf4j package imported by HelloServiceImpl is exported by a bundle
named "Sling-OSGi LogService Implementation".
Upload
your bundle jar file, press "Install or Update" and "Refresh Packages".
Your bundle should now show up in the list of bundles. If it has not
been started start it yourself by pressing "start".
Accessing the service
In order to be useful the deployed OSGi service should be accessible from esp templates. That works like this:
<% var service =
sling.getService(
Packages.com.day.samples.HelloService);
%>
<%= service.sayHallo() %>
The
HelloService also contains a method getReversedNodePath(Node node) that
takes a JCR node as a parameter (it diabolically returns the node's
path as a reversed string). For passing the currently processed node to
this method use:
<%= service.getReversedNodePath(currentNode)%>
The
method log(String text) in HelloService writes into Sling's log file.
This can come in handy for debugging purposes. Note again that the
logger package needs to be imported in MANIFEST.MF in order to be
visible.
In
the method getRepository() the name of the current repository is
returned. This method illustrates how to access the repository from
within the bundle and thus perform manipulations or queries on the
repository.
Final remarks
If
you care to look at Sling's source code to learn more you will notice
the lack of configuration files like serviceComponents.xml. The reason
for this is that the Sling develpers use a Maven plugin that
automatically generates these artifacts. You can still find them in the
generated jar files, of course.
To
learn more have a look at the sample applications that come with Sling.
Find them in samples/simple-demo and samples/webloader. The webloader
demo implements a background service that fills the repository with
publicly available files.
8. Multi-Site Management
Multi-Site
Management handles multilingual and multinational content, helping your
company balance centralized branding with localized content.
9.Building-workflows-in-adobe-cq5
--http://blog.navigationarts.com/building-workflows-in-adobe-cq5/
24. Explain LDAP Configuration and Synchronization in CQ5 ?
How does CQ interface with LDAP systems?
CQ
interfaces with LDAP systems, such as Apache Directory or Windows
Active Directory, using the Java Authentication and Authorization
Service (JAAS).
What LDAP information is synchronized with CQ?
Although
LDAP accounts might be assigned to groups, these associations often
reflect organizational properties, because the accounts may be applied
to multiple applications. It is recommended that you apply CRX groups to
the accounts to control permissions within CRX or any dependent
applications, such as CQ.
Additional reading:
ñ See this Help page for more information about administering users, groups, and access rights/permissions in CRX.
ñ For CRX user and group administration best practices, see this section.Information about users and groups is synchronized between CQ and the LDAP system.
How do I synchronize LDAP and CQ users?
To
synchronize LDAP users with CQ 5.5 Update 1, use the CQ JMX console
(http://localhost:4502/system/console/jmx) and go to
thecom.adobe.granite.ldap bundle.
The CQ com.adobe.granite.ldap bundle provides the following synchronization and purge commands:
ñ syncAllUsers - Updates all local user informations based on the LDAP directory
ñ syncUser - Updates the local user information for a specific LDAP entry
ñ syncUserList - Updates the local user information for a list of LDAP entries
ñ purgeUsers - Removes the local user information for all users removed from the LDAP server
Important: To use the com.adobe.granite.ldap bundle in CQ, you need to have CQ 5.5 Service Pack 1 installed.
Note:
CQ does not support reverse-synchronization. Any changes to the CQ user
list are not reflected back to your LDAP directory. To implement this
functionality, you will need to create a custom MBeans component. For an
introduction on how to create and develop MBeans in CQ see: Integrating Services with the JMX Console.
LDAP
user information is synchronized with CQ right when a new user tries to
log in to CQ. At this stage, the user may encounter a "No Resource
Found" error if she doesn't have access to any CQ resources yet. Before
the user can log in successfully, an administrator must grant her access
to appropriate CQ pages/resources.
LDAP group information is synchronized when the first user in the group attempts to log in to CQ.
The slave nodes in my clustered CQ setup are unable to connect to the LDAP server. What is the solution?
1. Ensure
that the java.security.auth.login.config property
in /crx-quickstart/bin/quickstart.bat points to the absolute file system
path of theldap_login.conf file. For example:
set CQ_JVM_OPTS=-Djava.security.auth.login.config=C:/crx-quickstart/conf/ldap_login.conf -Xmx1024m -XX:MaxPermSize=256M
set CQ_JVM_OPTS=-Djava.security.auth.login.config=C:/crx-quickstart/conf/ldap_login.conf -Xmx1024m -XX:MaxPermSize=256M
2. Archive the crx-quickstart folder on the master node of your CQ cluster as a ZIP file.
3. Copy this ZIP archive to each of the slave nodes and extract its contents to the same location as the master node.
4. Start CQ on the slave nodes using quickstart.bat.
Note: If
you're not running the Quickstart edition of CQ on your master node,
replicate the ldap_login.conf file on the master node in the
corresponding location on each slave node. Ensure that your startup
script (quickstart.bator a custom script) points to the correct location
of ldap_login.conf.
How can I interface CQ with multiple LDAP servers?
Refer to the following knowledgebase article.
How do I troubleshoot long-running CQ-LDAP synch operations?
Delayed
or "stuck" synchronization operations may be caused by problems with
the LDAP server or issues at the CQ end. Follow these troubleshooting
approaches:
ñ Ensure that the settings in your ldap_login.conf file are correct.
ñ Increase the log level of the LDAP module to DEBUG and look for messages in the log files. See this Help article for more information about CQ/CRX logs.
ñ Set up proxy logging between CRX/CQ and LDAP.
Note: Refer to this Help article for detailed information about these approaches.
If
you suspect an issue at the CQ end (rather than with the LDAP server),
consider making a thread dump for troubleshooting. See this Help article for more details.
CQ does not currently support dynamic LDAP groups.
How are the Quickstart file locations in CQ 5.5 different from those in CQ 5.4?
If
you're accustomed to configuring CQ 5.4/CRX 2.2 with LDAP, you'll
notice that some file locations have changed in CQ 5.5/CRX 2.3. In
particular, note the following:
ñ The location of the repository.xml file remains unchanged (crx-quickstart/repository/repository.xml)
ñ CQ 5.5 doesn't ship with a sample_ldap_login.conf file. You can copy and customize the text at this URL to create your sample ldap_login.conf file.
ñ (CQ 5.4) crx-quickstart/server/etc/ldap_login.conf --> (CQ 5.5) crx-quickstart/conf/ldap_login.conf
In general, the partial folder structures in CQ 5.4 and CQ 5.5 are as follows:
CQ 5.4
docs
launchpad
logs
opt
repository
server
bin
etc
launchpad
logs
opt
repository
server
bin
etc
CQ 5.5
app
bin
conf
launchpad
logs
monitoring
opt
repository
bin
conf
launchpad
logs
monitoring
opt
repository
Configuring
CQ with LDAP for Single Sign On (SSO) requires that you
set trust_credentials_attribute="TrustedInfo" in ldap_login.conf. See this page for more details.
How do I configure LDAP over SSL?
See "Configuring LDAP over SSL" at this page.
25. How to create a custom widget client-library ?
CQ5
provides an interface to add new JavaScript functionality to the WCM
authoring interface through the Ext.JS framework. These so-called
client-libraries provide the following:
ñadd custom functionality or
ñoverride and extend existing features
Create custom client-library
The next steps outline what is required to build a custom client-library.
ñGoto CRXDE Lite (e.g. http://<host>:<port>/crxde)
ñCreate a node with type cq:ClientLibraryFolder, e.g.
ñ/apps/myapp/ui/mylib
ñset the String property sling:resourceType to widgets/clientlib
ñset (multi-value) property categories to one or more of the following
Category Name
|
Description
|
cq.wcm.admin
|
SiteAdmin and Tools
|
cq.wcm.edit
|
ContentFinder and edit page
|
cq.dam.admin
|
DAM Admin
|
cq.dam.edit
|
DAM AssetShare, AssetEditor
|
if required, set (multi-value) String property dependencies to other client-libraries in the system
ñsave all changes
Overlaying / Adding widgets
ñCreate a source folder below the client-lib node, e.g.
ñ/apps/myapp/ui/mylib/source
ñCreate a file for each JS class and widget override, e.g.
ñ/apps/myapp/ui/mylib/source/MyWidget.js
ñ/apps/myapp/ui/mylib/source/override/ComponentList.js
ñCreate a file js.txt to include above created files in the custom client-lib:
#base=source
MyWidget.js
override/ComponentList.js
ñsave all changes
CQ5
automatically observes changes to a client-library in the repository
and will re-register this library for subsequent usage in the
corresponding category, e.g. when editing a page. Attached is an example
CQ content package that does the following:
ñadd custom client-library /apps/myapp/ui/mylib
ñcategory cq.wcm.edit
ñoverwrite default values of the component-list in the SideKick
ñdefault max number of component groups to be shown
ñdefault min number of components required for a group
26. How do I configure and connect to a JDBC DataSource?
CQ5 application needs to connect to an external RDBMS?
As an example we will create a JDBC DataSource to connect to H2 database engine Install the JDBC driver for your database.
ñ If your database vendor provides a JDBC driver jar as an OSGi bundle then you can deploy it directly into Felix Console.
ñ If
OSGi bundle with your driver is not available you can add the jar to
the shared classpath of your application server, for example
crx-quickstart/server/lib/container under CQSE, and create an Extension
Bundle.
ñ Create manifest file. For this example we will call it h2ext.mf. See below code listing.Note that the blank line at the end of a jar manifest file is required.
ñ Create a jar file with above manifest using the following command.
jar -cfm org.h2.jdbc.driver.extension-1.1.119.jar h2ext.mf
ñ Install
org.h2.jdbc.driver.extension-1.1.119.jar using Felix Console. This
should add org.h2 package to the export list of the System Bundle.
ñ Please refer to section 3.15, Extension Bundles, of the OSGi Service Platform Core for more information about Extension Bundles.
ñ Another
option is to embed the jdbc driver into another OSGi bundle. If you are
using CRXDE to create an OSGi bundle you can put the driver jar into
the bundle lib directory. CRXDE will automatically embed it.
ñ Another
option is to add the jar to the shared classpath of your application
server and use org.osgi.framework.bootdelegation property in
sling.propeties to load the driver class. Clickhere for more information. For example if you are using H2 database,
copy h2-1.1.119.jar to crx-quickstart/server/lib/container. Then add
the line "sling.bootdelegation.class.org.h2.Driver=org.h2" to
sling.properties.
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.h2.jdbc.driver.extension
Bundle-Version: 1.1.119
Fragment-Host: system.bundle; extension:=framework
Bundle-Name: H2 JDBC Driver Extension
Bundle-Description: Bundle exporting H2 JDBC Driver
Export-Package: org.h2
|
Configure JDBC Connection Pool
Naviagte to the Cofiguration Manager in the Felix console (http://localhost:4502/system/console/configMgr).
Use JDBC Connection Pool configuration factory to create a new
connection pool. For Example it might have the following settings.
JDBC driver class: org.h2.Driver
JDBC connection URI: jdbc:h2:~/test
Usename: sa
Password:
Validation query:
Pool size: 10
Pool wait (msec): 100
Datasource name: h2DataSource
|
Get an instance of the DataSource.
Once
configured the DataSource instance is acquired by calling
getDataSource(String datasourceName) method of DataSourcePool service
(com.day.commons.datasource.poolservice.DataSourcePool) and passing it
the datasource name.
OSGi Component Example
In
this example we are creating a simple OSGi service which can be used to
get an instance of a DataSource. This example is not realistic, since
it basically reinvents the same API as
com.day.commons.datasource.poolservice.DataSourcePool itself without
adding any functionality. But it shows how DataSourcePool can be used in
your own code.
Lets first create an interface for our service.
package com.day.test.datasource;
import javax.sql.DataSource;
public interface DatasourceUtil {
public DataSource getDataSource(String dataSourceName);
}
|
Now the implementation. As you can see besides hiding the DataSourceNotFoundException it does not add any value :).
package com.day.test.datasource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import com.day.commons.datasource.poolservice.DataSourceNotFoundException;
import com.day.commons.datasource.poolservice.DataSourcePool;
/**
*
* This class is an example if how DataSourcePool can be used to obtain the DataSource.
*
* @scr.component immediate="true" metatype="no"
* @scr.service interface="DatasourceUtil"
* @scr.property name="service.description" value="Data Source lookup example"
* @scr.property name="service.vendor" value="Day Software"
*/
public class DatasourceUtilImpl implements DatasourceUtil {
private static final Logger log = LoggerFactory.getLogger(
DatasourceUtilImpl.class);
/** @scr.reference policy="static" */
private DataSourcePool dataSourceService;
public DataSource getDataSource(String dataSourceName) {
log.info("Using DataSourcePool service lookup " +
"to get connection pool " + dataSourceName);
DataSource dataSource = null;
try {
dataSource = (DataSource) dataSourceService.getDataSource(
dataSourceName);
} catch (DataSourceNotFoundException e) {
log.error("Unable to find datasource {}.", dataSourceName, e);
}
return dataSource;
}
}
|
This
class is using OSGi Declarative Services specification to get an
instance of DataSourcePool service and then calls its
getDataSource(dataSourceName) to get the DataSource. Maven SCR Plugin is
using the the scr java annotations to generate the XML descriptors for
OSGi Declarative Services. The attached zip file contain the example
POM.
You can download a complete example here: datasourceutil.zip. It includes a maven POM to build it. In order to build this project using POM provided please refer to How to use CQ5 as maven repository.
JSP Example
This is a CRX package that contains a JSP example - datasource-example-jsp.zip. It"s a CQ component that can be added to any page with a paragraph system. It can be used to test your DataSource connection.
5.3 Note
Added
is a sample bundle to build with CRXDE / CRXDE Lite that contains the
oracle driverinstall the oracle_example_driver.zip, have a look at the
/apps/oracle.In the Activator.java it explicitly load the driver class
(it may not be required in future releases).Make sure you have the
latest day.commons.datasource.jdbcpool (1.0.8) installed before using
it.
27. Create a Sling Servlet by annotation in CQ5.5 ?
1. Create Servlet class
/**
* @scr.component immediate="true" metatype="false"
* @scr.service interface="javax.servlet.Servlet"
* @scr.property name="sling.servlet.methods" value="GET"
* @scr.property name="sling.servlet.paths" value="/myservlet"
* @scr.property name="sling.servlet.extensions" value="jsp"
*/
@SuppressWarnings("serial")
public class MyServlet extends SlingSafeMethodsServlet {
@Override
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
response.setContentType("text/plain");
response.getOutputStream().print("DDDDDDDDDDDDDD");
}
}
2. Create file pom.xml to build file jar bundle -> Success
3. Install on OSGi -> sucess and I can see the information and it's active as well
Service ID 1665 Types: javax.servlet.Servlet
Service PID: mh.osgitest.MyServlet
Component Name: mh.osgitest.MyServlet
Component ID: 1926
4. I also check on components tab (http://localhost:4502/system/
console/components) and see the information about this servlet also
mh.osgitest.MyServlet
Bundle mh.studies.sling.osgitest (242)
Implementation Class mh.osgitest.MyServlet
Default State enabled
Activation immediate
Configuration Policy optional
Service Type service
Services javax.servlet.Servlet
Properties component.id = 1926
component.name = mh.osgitest.MyServlet
service.pid = mh.osgitest.MyServlet
sling.servlet.extensions = jsp
sling.servlet.methods = GET
sling.servlet.paths = /myservlet
And status is active!
5. Test this servlet on browser but not success: http://localhost:4502/myservlet.jsp -> got 404 error
6. I tried with request http://localhost:4502/myservlet.json it gives exactly servlet info
{
"sling:resourceType":"/myservlet.servlet","servletClass":"mh.osgitest.MyServlet",
"sling:resourceSuperType":"sling/bundle/resource","servletName":"mh.osgitest.MyServlet"
}
FAQ :Why the Error is Coming?
Answer :
Here is the problem, why u can't access those url with jsp.
sling.servlet.extensions property is ignored if the sling.servlet.paths
property is set. except inbuild extension json, xml and html, you can't
use other extension.
so
when u overridden some not implemented methods means smhow internally
system manage to provide response for request. but Ideally to handle
post method, we have to use SlingAllMethodsServlet.
Just remember to add this annotation when declare new servlet
* @scr.property name="sling.servlet.resourceTypes" value="sling/servlet/
default" @scr.property name="sling.servlet.resourceTypes" value="sling/servlet/default"
28. Simple steps to create a HTTP Servlet in CQ5.5
These are steps that we can register a HTTP Servlet as a service on
OSGi bundles
Step 1: Create new bundle in CRXDE
Step 2: Create new class extends class HttpServlet
public class HelloWorld extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
resp.getWriter().write("Hello World!");
}
protected void doPost(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
}
}
Step 3: In Activator.java register the HelloWorld servlet with path /hello
public void start(BundleContext context) throws Exception
{ ServiceReference sRef =
context.getServiceReference(HttpService.class.getName());
if (sRef != null) {
HttpService service = (HttpService)
context.getService(sRef);
service.registerServlet("/hello", new HelloWorld(), null,
null);
}
}
Step 4: Build the bundle
Step 5: Check the new bundle in OSGi console http://localhost:4502/system/console/bundles
Step 6: Test the new servlet. http://localhost:4502/hello -> Hello World!
FAQ :
1. Why don't you use annotations; example:
@SlingServlet(methods = "GET", paths = "/bin/pathtoservlet/myServlet")
public class TestServlet extends SlingSafeMethodsServlet {
//your servlet code here
}
Answer :
we
can create simple httpservlet but if we don't use annotation, ur
servlet will be not registered as sling component. so there is no harm
create simple servlet but if you wanna request as sling REST approach. u
hv to use annotations.
You
are right in this case just create a simple HTTP Servlet, if need to
register as sling component (for using objects such as session, sling
...) we should use annotation or maven plugin builing
for this
2. Can any one tell me that how can we registered the newly created servlet in Activator.java.
Answer :
You can follow these steps:
1. Create new class with annotation:
/**
* @scr.component immediate="true" metatype="false"
* @scr.property name="sling.servlet.resourceTypes" value="sling/servlet/default"
* @scr.service interface="javax.servlet.Servlet"
* @scr.property name="sling.servlet.paths" value="/path/to/servlet"
*/
2. Create a Maven pom.xml file to build this class into jar bundle
3. Install this jar on Felix bundle console,
29. How to Reference OSGI services inside a Java class?
I
just want to reference the SlingRepository and the
JcrResourceResolverFactory inside a Java class. I tried it with the
@scr.reference tag as follows:
/**
* @scr.reference
*/
private SlingRepository repository;
/**
* @scr.reference
*/
private JcrResourceResolverFactory resolverFactory;
If
I look at the generated class file, the bind and unbind methods for
this services are inserted, so I think it should works. But the objects
SlingRepository and JcrResourceResolverFactory are still null!
If
you use the @scr.reference tags you are trying to create Declarative
Services componnent to do this you also have to set the @scr.component
tag in the Class Level JavaDoc and -- depending on your build
environment -- use the Maven SCR Plugin (if you are using CQDE, this
would be built in).
If
this is a regular bean object, it is a bit more complex, since you
control the instantiation your self. So you have to grab the service
from the OSGi service registry manually.
FAQ :
1. How can I grab the service manually from the OSGI service registry?
Answer :
If you are in a JSP Script you can do
<cq:defineObjects />
<%
ServiceType service = sling.getService(ServiceType.class);
%>
If you are in ECMA/ESP you can do
<%
var service = sling.getService(Qualified.ServiceType);
%>
Hope this helps.
Out of a jsp, it works fine to get the service. But I'm still trying,
to get the service out of a Java class.
This is my SampleService:
/**
* @scr.component immediate="true"
* @scr.service interface="SampleService"
*/
public class SampleServiceImpl implements SampleService {
/**
* @scr.reference
*/
private SlingRepository repository;
/**
* @scr.reference
*/
private JcrResourceResolverFactory resolverFactory;
public String sayHello() {
try{
Session session = repository.loginAdministrative(null);
ResourceResolver rr = resolverFactory.getResourceResolver(session);
PageManager pageManager = rr.adaptTo(PageManager.class);
Page page = pageManager.getPage("/content/kanton_st_gallen/
testseite");
return "The SampleService says hello " + page.getTitle();
}catch(Exception e){
return "SampleService failed!";
}
}
}
And this is my test class, where I try to get the service:
/**
* @scr.component
*/
public class Test{
/**
* @scr.reference
*/
private SampleService sampleService;
public String getSampleServiceMessage(){
try{
return sampleService.sayHello();
}catch(Exception e){
return "SampleService failes";
}
}
}
Isn't this possible like this?
Sure, this is perfectly possible (just make sure to use real packages
and not the default package)
If you are using CQSE to develop this code, everything should be set for
you for this to work.
If you are using Maven to build your bundles, you have to make sure to
configure the Maven SCR Plugin [1] for the required descriptors to be
generated.
30. How to get CQ Services ?
I
am writing a java code outside cq to generate a report on certain
pages.I am connecting to the server using client repository and getting
the session.
ClientRepositoryFactory factory = new ClientRepositoryFactory();
javax.jcr.Session s = null;
String crxApplicationName = "crx";
String repoUrl = (new StringBuilder(_resourceBundle.getString("HOST_NAME"))).append(crxApplicationName).toString();
String workspace = "crx.default";
String username = _resourceBundle.getString("USER_NAME");
char password[] = _resourceBundle.getString("PASSWORD").toCharArray();
try
{
Repository repository = factory.getRepository(repoUrl);
s = repository.login(new SimpleCredentials(username, password), workspace);
System.out.println((new StringBuilder("userId:")).append(s.getUserID()).toString());
}
FAQ:
What
my doubt is is it possible to get the cq services like pagemanager
factory, cq classes like Resource Resolver. I means is it possible to
use all the API's that we use when we wite a code in cq.If possible can
anyone guide me in doing so.
Answer :
Try something like this.
bundleContext.getService(bundleContext.getServiceReference("com.day.cq......"))
31. How do I convert an existing jar file into an OSGi bundle?
Here's a very simple way of turning an existing jar file in an OSGi bundle, while keeping control on exported packages.
The example creates an OSGi bundle from the attached junit-4.4.jar.
Note: The method below only works in a scenario where the jar file has no dependencies on other external jar files.
1. Start by creating a the jar's manifest file:
Manifest-Version: 1.0
Created-By: myself
Bundle-ManifestVersion: 2
Bundle-Name: JUnit 4.4 bundle
Bundle-Description: Package junit 4.4 in an OSGi bundle
Bundle-Version: 4.4.0
Bundle-ClassPath: .,junit-4.4.jar
Bundle-SymbolicName: org.junit.framework
Export-Package: junit.framework,junit.extensions,org.junit.runner,org.junit,junit.textui
ñ Bundle-ClassPath header
is set to allow embedding the original jar as is. Make sure its value
matches the filename of the jar that you are going to embed in the
bundle.
ñ Export-Package is
a list of packages contained in the jar that you would like to make
available to other bundles running in the OSGi Container.
2. Jar file
Get the jar file, in our case from
Get the jar file, in our case from
- Create the bundle jar file by running the following command:
jar cvfm junit-4.4-bundle.jar manifest.txt junit-4.4.jar
4. Where manifest.txt is the name of the manifest file created above.
That's it - the resulting jar file (attached to this page as an example) is an OSGi bundle the exports the packages listed in Export-Package above, using the classes of the embedded junit-4.4.jar.
That's it - the resulting jar file (attached to this page as an example) is an OSGi bundle the exports the packages listed in Export-Package above, using the classes of the embedded junit-4.4.jar.
32. Sling Authentication:
This section describes the framework provided by Sling to authenticate HTTP requests.
Let's
look at generic request processing of Sling: Sling is linked into the
outside world by registering the Sling Main Servlet -- implemented by
the SlingMainServlet class in the Sling Engine bundle -- with an OSGi
HttpService. This registration is accompanyied with an implementation
instance of the OSGi HttpContext interface, which defines a method to
authenticate requests: handleSecurity.
This
method is called by the OSGi HTTP Service implementation after the
servlet has been selected to handle the request but before actually
calling the servlet's service method.
{section} {column}
{column}
{column} 1. First the OSGi HTTP Service implementation is analyzing the
request URL to find a match for a servlet or resource registered with
the HTTP Service. 1. Now the HTTP Service implementation has to call the
handleSecurity method of the HttpContext object with which the servlet
or resource has been registered. This method returns true if the request
should be serviced. If this method returns false the HTTP Service
implementation terminates the request sending back any response which
has been prepared by the handleSecurity method. Note, that the
handleSecurity method must prepare the failure response sent to the
client, the HTTP Service adds nothing here. If the handleSecurity method
is successful, it must add two (or three) request attributes described
below. 1. When the handleSecurity method returns true the HTTP Service
either calls the Servlet.service method or sends back the requested
resource depending on whether a servlet or a resource has been selected
in the first step. {column} {section}
The
important thing to note here is, that at the time the handleSecurity
method is called, the SlingMainServlet is not yet in control of the
request. So any functionality added by the SlingMainServlet, notably the
SlingHttpServletRequest and SlingHttpServletResponse objects are not
available to the implementation of the handleSecurity method.
The following pages describe the full details of request authentication in Sling in full detail:
- Tasks: Authentication of HTTP Requests is generally a two-step process: First the credentials must be extracted from the request and second the credentials must be validated. In the case of Sling this means acquiring a JCR Session.
- Actors: The authentication process involves a number of actors contributing to the concepts, the API and the particular implementations.
- Framework: The core piece of functionality with respect to authentication in Sling is contained in the Sling Commons Auth bundle. This bundle provides the API for Sling and Sling applications to make use of authentication.
- AuthenticationHandler: The {{AuthenticationHandler}} interface defines the service API which may be implemented by authentication handlers registered as OSGi services.
33. Stateful and Stateless System Architectures
Both stateful and stateless architectures each have their own advantages and disadvantages. A few are listed here:.
Stateful
Stateful systems have the following advantages:
· They include a predictable and reasonable number of connections.
· A predictable number of resources are required to keep system running.
· There is the possibility of using session-level features to optimize performance (temporary tables, packaged variables, etc.)
· Since all activities are happening in the same session, there is no need to reload packages/execution plans to the memory.
The main (but significant disadvantage is that stateful systems do not scale well )
Stateless
Stateless systems have the following advantages:
· At any point in time, there are only a small number of sessions connected to the database
· The workload typically follows a statistical trend.
The following disadvantages can be associated with stateless system architectures:
- Keeping a persistent layer is difficult and there are different schools of thought about where to place it (database/middle tier/client), not to mention how to go about it. (For more details about this topic, see my RMOUG 2008 paper “Stateful vs. StateLESS for Database Developers”).
- Each physical session must be opened and closed. If you do this thousands of times, it becomes expensive, especially if your code is PL/SQL-intensive, because each package must be reloaded and reinitialized
- Workload is more or less statistically even, so it is difficult to manage possible unpredicted activity spikes.
- It is clear, that stateless solutions were able to solve the core scalability problem since they made it possible to build systems that would scale up to thousands if not hundreds of thousands of simultaneous users. However, the costs were too high for the following reasons:
- Managing the persistent layer is time-intensive.
- There are significant performance impacts of the activities required to manage a huge number of separate physical requests.
- There is only a low level of control over how many sessions are executed at any point in time.
34. How to Manage Events in Sling
Apache Sling provides some mechanisms and support for managing events.
The
event mechanism is leveraging the OSGi Event Admin Specification (OSGi
Compendium 113). The OSGi API is very simple and lightweight. Sending an
event is just generating the event object and calling the event admin.
Receiving the event is implementing a single interface and declaring
through properties which topics one is interested in. Sling makes a
distinction between events and job events. Unlike events, job events are
garanteed to be processed. In other words: someone has to do something
with the job event (do the job).
This
page drives you through the implementation of two services that rely on
the Sling eventing mechanisms. The services implement the following use
case: whenever a file is uploaded to a temporary location in your web
application, the file is moved to a specific location according to its
MIME type.
Introduction
You will now implement the logic to listen to files posted to /tmp/dropbox and to move them to the appropriate locations depending on the MIME type:
- images (.png) are moved to /dropbox/images/
- music (.mp3) are moved to /dropbox/music/
- movies (.avi) are moved to /dropbox/movies/
- otherwise the files are moved to /dropbox/other/
To do that, you will implement two services. The first one, called DropBoxService:
- Listens to OSGI events.
- Sends a job event if a resource has been added to /tmp/dropbox.
The second one, called DropBoxEventHandler:
- Listens to the former job event.
- Moves the file according to its extension.
Listening to OSGI Events
To listen to the specific OSGI event resource added the property event.topics* needs to be set to org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED** in the class annotations.
1
2
|
@Property(name="event.topics",
value=org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED)
|
You can refer to the org.apache.sling.api.SlingConstants class in the Javadocs to know about other events available in Sling.
Sending Job Events
To
send an event the following code can be used: #!java public void
sendEvent() { final Dictionary props = new Hashtable();
props.put(JobUtil.PROPERTY_JOB_TOPIC, JOB_TOPIC);
props.put("resourcePath", RESOURCE_PATH); final Event myEvent = new
Event(JobUtil.TOPIC_JOB, props); eventAdmin.sendEvent(myEvent);
However, for our example, to send a job event the service needs to implement the org.osgi.service.event.EventHandler and org.apache.sling.event.JobProcessor interfaces:
1
|
public class DropBoxService implements JobProcessor, EventHandler {
|
To send the job event the Event Admin service needs to be referenced:
1
2
|
@Reference
private EventAdmin eventAdmin;
|
The job topic for dropbox job events needs to be defined:
1
2
|
/** The job topic for dropbox job events. */
public static final String JOB_TOPIC = "com/sling/eventing/dropbox/job";
|
The org.osgi.service.event.EventHandler#handleEvent(Event event) method needs to be implemented:
1
2
3
4
5
|
public void handleEvent(Event event) {
if (EventUtil.isLocal(event)) {
EventUtil.processJob(event, this);
}
}
|
The org.apache.sling.event.JobProcessor#process(Event event) method needs to be implemented:
Its logic is as follows:
- The OSGI event is analyzed.
- If the event is a file that has been added to /tmp/dropbox:
· An event is created with 2 properties:
· A property to set the event as a job event.
· A property for the file path.
· The job event is sent to all the listeners that subscribe to the topic of the event.
java
public boolean process(Event event) {
// get the resource event information
String propPath = (String) event.getProperty(SlingConstants.PROPERTY_PATH);
String propResType = (String) event.getProperty(SlingConstants.PROPERTY_RESOURCE_TYPE);
// an event is sent if a file is added to /tmp/dropbox
if (propPath.startsWith("/tmp/dropbox") && propResType.equals("nt:file")) {
// configure the job event
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(EventUtil.PROPERTY_JOB_TOPIC, JOB_TOPIC);
props.put("resourcePath", propPath);
// create the job event
Event dropboxJobEvent = new Event(EventUtil.TOPIC_JOB, props);
// deliver the job event
eventAdmin.sendEvent(dropboxJobEvent);
log.info("the dropbox job has been sent: {}", propPath);
}
// all set and done
return true;
}
Listening to Job Events
Now that you have implemented a service that sends a job event when a file is uploaded to /tmp/dropbox, you will implement the service DropBoxEventHandler that listens to those job events and moves the files to a location according to their MIME types.
To listen to the job events that have been defined before the property event.topics needs to be set to mypackage.DropBoxService.JOB_TOPIC in the class annotations:
1
2
|
@Property(name="event.topics",
value=mypackage.DropBoxService.JOB_TOPIC)
|
Handling Job Events
To move the files the service needs to implement the org.osgi.service.event.EventHandler and org.apache.sling.event.JobProcessor interfaces:
1
|
public class DropBoxEventHandler implements JobProcessor, EventHandler {
|
Some class fields need to be defined:
- The default log.
- The references to the SlingRepository and the JcrResourceResolverFactory services, which are used in the implementation.
· The destination paths of the files.
· java
/* Default log. / protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Reference private SlingRepository repository;
@Reference
private JcrResourceResolverFactory resolverFactory;
private JcrResourceResolverFactory resolverFactory;
private
final static String IMAGES_PATH = "/dropbox/images/"; private final
static String MUSIC_PATH = "/dropbox/music/"; private final static
String MOVIES_PATH = "/dropbox/movies/"; private final static String
OTHER_PATH = "/dropbox/other/";
The org.osgi.service.event.EventHandler#handleEvent(Event event) method needs to be implemented:
1
2
3
4
5
|
public void handleEvent(Event event) {
if (EventUtil.isLocal(event)) {
EventUtil.processJob(event, this);
}
}
|
The org.apache.sling.event.JobProcessor#process(Event event) method needs to be implemented.
Its logic is as follows:
- The resource path is extracted from the job event property.
- The resource is obtained from the resource path.
- If the resource is a file, the destination path is defined based on the file MIME type.