Blogroll

Tech Travels

url

In this short article (first of a serie I hope) I’ll show you how to create a Sling Servlet in CQ.

Scenario

You are migrating your existing application in CQ a piece at time and it’s time for the Servlets (controllers) part, so for the first stage you’d like to keep the old URLs. Maybe because some other external services are calling you at these coordinates or because you don’t want to enter each jsp and change the forms action.

Ingredients

CQ instance running in Author (localhost:4502)

CRXDE (let’s ease the game for starting)

Process

Create a new OSGi bundle under geometrixx (or your app). In this create a new class that extends the SlingSafeMethodsServlet.
Then you have to register as a service in the OSGi container. This is done using the Felix annotations as following:

Looking at the sling.servlet.paths annotation we se on which url we are actually mapping the servlet: /path/to/my/servlet and /apps/path/to/my/servlet.

Building the bundle and CRXDE+felix will do the magic of the deployment.

Now if you try to run localhost:4502/apps/path/to/my/servlet you’ll see our beautiful Helloworld, but if you’ll try to access localhost:4502/path/to/my/servlet you’ll get a 404 or a content listing.
This is due to a settings in felix+Sling. Open the felix console at the configuration tab (/system/console/configMgr) and search for Apache Sling Servlet/Script Resolver and Error Handler. Here you’ll have to add “/path/” to the Execution Paths section.

Don’t know why. Don’t ask it to me. I only know that the custom rewrite/redirect I made in my J2EE filter didn’t work until I told middleware office to set a websphere custom property.

The property to set is com.ibm.ws.webcontainer.invokefilterscompatibility and has to be set to true. You can find where to set it under the websphere administration console following this path Application Servers -> <server> -> Web Container Settings -> Web Container -> Custom Properties.

Sooner or later it happens that you have to access an https via Java. Accessing a generic http (non ssl) site is quite easy using the URL and URLConnection objects.

When you try to access a site through SSL the main problem is that most sites does not have a registration in the java’s Certificate Autorithy (CA), causing the framework to refuse connection to that site. So the main solution is to register the certificate of that site in the java’s CA.

So, the things to do are:

download the site certificate

register it in the java’s CA

accessing the site

Downloading the certificate

In order to download the certificate we are gonna use Firefox. With firefox navigate to the site and if required accept the certificate. Double click on the icon of the certificate (1), in the screen that appear choose view certificate (2), on details tab (3) use the export button (4) and save it wherever you want (5).

Register the certificate

Once downloaded the .cer file (X 509 Certificate DER), you can import it into the CA using the a command line program deployed with the j2se installation: keytool.

Java’s CA and keytool are available in the $JAVA_HOME/lib/security/ and an example of using the keytool (under windows) is the following

Maybe if you are using eclipse, you will have to restart the workbench in order to make the registration visible to the jvm.

The main counterpart of using this approach is that you have to register the certificate for each jvm running the program and since certificate can expire you should have to do this operation more than one time. I advise to automate the registration operation with a shell script to be distributed among with the program.

Accessing the site

Once registered the site’s certificate, you can access it as usual using the URL and URLConnection objects. It should be enough to tell (via System.properties) an SSL provider. Here is a PDF with the code.

When I was ready for production environment, during tests I wondered that the AppError is ignored when core debug level is set to 0. While I’m asking about the utility of this behavior, I asked in the list and searched for a solution.

One solution could be to take the __construct method from the ErrorHandler, removing the Configure::read() test and paste it into the AppError::__construct() without calling the parent::__construct(). But in this way if some new feature, fixes, etc. is distributed within that method you’ll probably miss it until you monitor each release.

Finally I opted for useing the routes.php file mapping each action and then mapping the “missing action” to the controller::view() action and the manage the code inside it. Here is a PDF with an extract of the code.

The task was to have “aliases” for url. For example let’s think about a ProjectsController; each project is characterized by a unique id, a unique name and some other attributes. With the cake way you can refer to the projects with /projects/add, /projects/edit/$id, /projects/delete/$id and /projects/view/$id.

I would like to have an alias for the view: call each project even with a url like /projects/$name (friendlier url).

I achieved the task extending the ErrorHandler::missingAction(). Here is the code I used (pdf).