Latest Posts

Archives [+]

Archive for 'May 2008'

    Posted by Lars Trieloff MAY 30, 2008

    Posted in social Add comment

    In my second presentation I tried to be less controversial, at least in the title. In "Creating Value in Social Networking" I took the product manager's point of view to define social networking by analyzing existing popular social networks feature-by-feature. From this feature-oriented approach we took a look at some ways of monetizing social networks, which is actually much easier if you are not a pure social network, but already have valuable content that you enhance by adding social relevancy. Even better, when you already have a revenue model the social networking features can increase visitor loyalty and boost your revenues.



    Posted by Lars Trieloff MAY 30, 2008

    Posted in crx, jcr, osgi, rest and sling Comment 1

    Coming back from our customer and tech summit in Chicago, I have to say it has been a great event, even if you do not consider the Cubs vs. Dodgers game we attended. I have met many interesting people, had great conversations with customers, partners and colleagues and we had some interesting discussions about my talk in the technical track: The Zero Bullsh*t Architecture. The slides are already up on slideshare.net

    The basic idea of this talk is that you have to analyze your requirements and concepts throughoutly, that you cannot design a proper architecture on autopilot, and of course that if you are building content centric applications, you should use a content repository as the storage layer and not try to implement all the content repository features on your own spread across architectural layers.

    Posted by Michael Marth MAY 23, 2008

    Posted in cms, communique, osgi, rest and sling Comments 5

    One of the aspects in CMS projects that routinely pops up is the integration of the CMS-based application with some other web application. For example, consider a CMS-based brochure-style web site and an e-banking application. Typically, these are implemented in different systems, but shall be presented to the user in a unified fashion.

    Many of Day's customers have a large investment in Spring-based applications which comes as no surprise as Spring is certainly the 800 pounds gorilla in the Java frameworks space these days. Thus, Day developer Alex Klimetschek and I met with Sandro Ruch and Jan Stettler of Day partner company Namics to discuss ways to integrate Communique 5 and Spring-based applications. Sandro and Jan look back to years of experience in Communique and Spring and delivered a large number of projects based on each of them.

    The results of this workshop to combine CQ5/Sling-based and Spring-based applications were slightly surprising: it is just so easy. Due to the standards-based approach of Sling the integration boils down to two very simple scenarios:

    Spring application in Sling

    In this scenario a Spring-based application shall be used from within a Sling-based application. A typical use case would be the integration of legacy data.

    The solution for this use case is based on Spring's Dynamic Modules. Dynamic Modules enable Spring application to be deployed in an OSGi container. Since Sling runs on OSGi the Spring application can be deployed into Sling and is afterwards available as an OSGi service. The service's exposed classes and methods are accessible from the Sling view's as any other service.

    This integration approach allows Spring developers to develop and test application components that have no dependencies on the content management system. The OSGi-based deployment approach further decouples development cycles of the web developer and the Spring developer.

    I intend to write up a little tutorial on deploying Spring apps into Sling (but if you do not want to wait give it a try, it is really easy). A post on deploying regular OSGi beans (without Spring) in Sling is already available.

    Access to content from Spring application

    The integration approach above is most suitable for "headless" Spring apps, i.e. for applications that consist solely of business logic and do not contain a web tier. If the Spring application is a complete web application the typical integration problem is how to access CMS-managed content from the Spring beans.

    Of course, CQ5 is JCR-compliant so the content can be accessed through standard JCR connections (there is also a Spring JcrTemplate available). However, with Sling things get even simpler: the CMS can get accessed through the REST. All nodes and trees are already available in JSON and plain text format and XML will soon follow. So integrating the content really just involves sending HTTP requests. This approach will carry you very far without having to resort to JCR connections (but it surely feels comforting that this lower level access is always there).

    You might have noticed it already: REST-based content integration is not confined to Spring or even Java. Sling opens up JCR-based content to any system that speaks HTTP (see also the discussion here).

    Next week, I will post on integrating Sling, Spring and Swing to Splwing... Just kidding.

    Posted by Michael Marth MAY 23, 2008

    Posted in http, rest, sling and tutorial Comments 8

    Back in November last year I wrote a post about Sling's request processing. Things have changed quite a bit till then so here's a revised version.

    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.

    Posted by Michael Marth MAY 22, 2008

    Posted in cms, everything is content and link of the day Add comment

    Seth Gottlieb has written an excellent post on how content is different from data. He also outlines features of a content management application that distinguish it from a database application.

    Posted by Michael Marth MAY 15, 2008

    Posted in osgi, sling and tutorial Comments 7

    About a week ago I posted on how to create an OSGi bundle for Apache Sling. In the comments section of that post Sling developer Bertrand Delacretaz mentioned that the Maven build tool might save some work in that respect. Inspired by that comment I would like to show in this post how to convert the example to a Maven build.

    If you have not done so start off by downloading and installing Maven and get familiar with the basic concepts, especially the pom.xml file where the build is configured.

    A big advantage of using Maven for building OSGi bundles for Sling is that the descriptor files serviceComponents.xml and MANIFEST.MF are automatically generated from Java annotations in the source files. Therefore, it is not necessary anymore to explicitly write any descriptor files when Maven is used. Instead, a number of annotations need to be added to the HelloServiceImpl class:

    ...
    /** HelloService implementation
    *
    * @scr.service
    *
    * @scr.component
    * immediate="true"
    * metatype="false"
    *
    * @scr.property
    * name="service.description"
    * value="A sample from Day"
    *
    * @scr.property
    * name="service.vendor"
    * value="Day"
    *
    */
    
    public class HelloServiceImpl implements
      HelloService{
    
    /** @scr.reference */
    private SlingRepository repository;
    ...
    

    Maven will process the @scr. annotations. For example, the @scr.property annotations get converted into scr:property elements in serviceComponents.xml.

    The @scr.reference annotation is even more useful. Not only does it generate the corresponding element in serviceComponents.xml but it also generates the bind/unbind methods for the injection of the repository object. As a consequence these two methods can be removed from the source code of HelloServiceImpl.

    The rest of the configuration is done in the pom.xml file, especially the bits we need to get the correct MANIFEST.MF. Have a look at the attched pom.xml and consider the the lines

    <configuration>
      <instructions>
        <Export-Package>
        !com.day.samples.impl,
        com.day.samples.*
        </Export-Package>
        <Private-Package>
        com.day.samples.*
        </Private-Package>
      </instructions>
    </configuration>
    

    This configuration will be picked up by Maven. It will write into MANIFEST.MF:

    Export-Package: com.day.samples;uses:="javax.jcr"
    

    All imports the bundle needs do not have to be configured explicitly, but are generated automatically into MANIFEST.MF. Nice!

    Another useful feature is auto-deployment of the produced bundle into Sling. This is configured in pom.xml in the lines:

    <configuration>
      <slingUrl>
      http://localhost:8080/system/console/install
      </slingUrl>
      <user>admin</user>
      <password>admin</password>
    </configuration>
    

    Make sure to adapt your port and password accordingly. For CRX Quickstart the port is likely to be 7402.

    In order to enable Maven to find some additional (Maven) repositories that contain the Apache Snapshot two additional sections are necessary in pom.xml. See the parts repositories and pluginRepositories of that file.

    As usual, all sources discussed in this post are attached. Download the jar, unpack it and execute

    mvn install
    

    This will compile and deploy the bundle into Sling without further manual work.

    Posted by Lars Trieloff MAY 14, 2008

    Posted in ajax, jcr, osgi, rest and sling Add comment

    I presented yesterday at the Henry Stewart DAM Show in New York. My presentation explained that JCR as a standard is important for Digital Asset Management because you want to re-use your digital assets in other content-centric applications such as web content management, collaboration or document management, turning your requirement for a digital asset management system into an application platform for asset centric applications.

    I then explained the basic concepts behind JCR, REST, AJAX and OSGi, that all together form Sling, the fifth way of creating asset centric applications. For implementors of asset centric applications Communiqué DAM offers a big head start, because it offers you an user-friendly asset management interface, asset transformation and export services and defined API and data model for your application out of the box. Furthermore you can use our connectors to JCR-enable existing content repositories such as Microsoft Sharepoint or Vignette.

    As always, find the slides on slideshare…


    Posted by Greg Klebus MAY 13, 2008

    Posted in announcements, crx, crx quickstart, jcr and sling Add comment

    Finally! The Website for Day JCR Cup 2008 has been launched! Check out the website today to start using CRX Special Cup edition, dubbed "CRX Quickstart", and creating great content applications. Learn great technologies using CRX and win MacBook Pro.

    Thank you very much for waiting - we wanted to make sure that Apache Sling application framework for creating the contest applications would not change in a backwards-incompatible way, forcing contest participants to change their applications with next releases of Sling. And we wanted the CRX Quickstart edition to be really fun to use.

    To make up for the waiting, we decided to extend the submission deadline to September 30, 2008.

    Best of luck, and we can't wait to see your submissions.

    Posted by David Nuescheler MAY 13, 2008

    Posted in announcements, cms, day, ecm, jackrabbit, jcr, jsr-170 and sling Add comment

    Today I will speak at WebTuesday in Zurich, hosted by Cablecom.

    Feel free to join, it is going to be very exciting ;)

    Posted by David Nuescheler MAY 08, 2008

    Posted in announcements, cms, day, ecm, jcr and jsr-170 Add comment


    Yesterday I spoke at the at IDC's 4. Enterprise Content Management Conference 2008 in Mainz, Germany.


    Please find the slide deck below



    Posted by Michael Marth MAY 07, 2008

    Posted in osgi, sling and tutorial Comments 12

    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.

    Create a bundle

    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 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.