This category contains articles related to programming
A question from my colleagues in regards to AEM’s support for webp started a research path. Since, I took more than 1 year pause from AEM, I started looking around for the possibility of serving also webp images, for all the images already in DAM.
As a first step I started ask the community on stackoverflow and Adobe Forum. The answer received was to use a webp java library that provides support for reading and writing webp images .
Note: You will notice I have usedcom.github.nintha library. At the end of the article I will explain the reasoning for it and how I actually ditched it to work.
The steps for resolving this were:
In AEM one can install via in Apache Felix only bundled jar, for the simple jars, one can embed them using the maven-bundle-plugin in tree steps:
<dependency>
<groupId>com.github.nintha</groupId>
<artifactId>webp-imageio-core</artifactId>
<version>0.0.1</version>
</dependency>
2. Modify the pom.xml from the core app to add the dependency and embed the jar. The core/pom.xml will have something like:
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>javax.inject;version=0.0.0,*</Import-Package>
<Export-Package>andra.core.*</Export-Package>
<Sling-Model-Packages>
andra.core
</Sling-Model-Packages>
<Embed-Dependency>webp-imageio-core</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
....
<dependency>
<groupId>com.github.nintha</groupId>
<artifactId>webp-imageio-core</artifactId>
</dependency>
Things to mention: the Embed-Dependency tag needs to be populated with the artifactId. The <Embed-Transitive> tag specifies to embed also the dependencies of the embedded jar. (eg. the webp-imageio-core has as dependency org.scijava – native-lib-loader, which will be embedded as well)
In order to test that your 3rd party was successfully embedded, one can take a look at the bundle information:

For the purposes of this POC, it will be only a basic Servlet, it can be enhanced, of course to work with image renditions, or to work receive the path as a suffix – which would be the right way as we want the images to be cached.
package andra.core.servlets;
import com.day.cq.dam.api.Asset;
import com.luciad.imageio.webp.WebPWriteParam;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.servlet.ServletException;
import java.awt.image.BufferedImage;
import java.io.IOException;
@SlingServlet(paths = "/bin/webpTransformer",
methods = HttpConstants.METHOD_GET
)
@Properties({
@Property(name = Constants.SERVICE_DESCRIPTION, value = "WebP Transformer Servlet")
})
public class WepServlet extends SlingSafeMethodsServlet {
public static final String IMAGE_WEBP = "image/webp";
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
response.setContentType(IMAGE_WEBP);
BufferedImage image = getImage(request);
// Obtain a WebP ImageWriter instance
ImageWriter writer = ImageIO.getImageWritersByMIMEType(IMAGE_WEBP).next();
// Configure encoding parameters
WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("Lossless");
ImageOutputStream outputStream = new MemoryCacheImageOutputStream(
response.getOutputStream());
// Configure the output on the ImageWriter
writer.setOutput(outputStream);
// Encode
writer.write(null, new IIOImage(image, null, null), writeParam);
outputStream.flush();
outputStream.close();
}
private BufferedImage getImage(SlingHttpServletRequest request) throws IOException {
ResourceResolver resourceResolver = request.getResourceResolver();
String path = request.getParameter("path");
Resource res = resourceResolver.getResource(path);
Asset asset = res.adaptTo(Asset.class);
return ImageIO.read(asset.getOriginal().getStream());
}
}
A question I would ask is why use nintha over luciad, as in the end nintha is just a luciad wrapper. Of course, I always try to use the standard lib, where possible, however when embedding luciad compiled on my machine I would get the following error:
Could not initialize class com.luciad.imageio.webp.WebPEncoderOptions
Cannot serve request to /bin/webpTransformer in andra.core.servlets.WepServlet
Exception:
java.lang.NoClassDefFoundError: Could not initialize class com.luciad.imageio.webp.WebPEncoderOptions
at com.luciad.imageio.webp.WebPWriteParam.(WebPWriteParam.java:30)
at com.luciad.imageio.webp.WebPWriter.getDefaultWriteParam(WebPWriter.java:38)
After a couple of days, I decided to give nintha a go. However, it did not go as smooth as I wanted, as know I would receive:
org.scijava.nativelib.NativeLibraryUtil Problem with library
java.lang.UnsatisfiedLinkError:
Meaning, that the native library included in nintha was not compatible with the OS the app was running. So, I had to add compile the native app on my local machine, add it manually to the nintha library and recomile. This is not a solution I like as it would be a downside when migration to another server – the library needs to encapsulate the native app for the specific environment.
I will write about what something I found funny – the conditions
This was all from my Python adventure till this moment.
I always enjoyed stuff that had to do with programming languages and learning how to set your mind to new things/paradigms. One of my favourite courses in the University was Logic and Functional Programming – learning Prolog and LISP (Let’s Insert Some Parenthesis :D).
I played a little bit with Python for my Mater’s Thesis (Static vs Dynamic Typed Programming Languages) some years ago and I always wanted to go a little bit more in depth with it. So, now I considered it to be a great time to restart playing with Python.
The syntax I consider it to be pretty straightforward and there is quite a good documentation on the internet. But, somehow I felt I was missing the Java API docs format. For me it is more convenient to search for something and see what else I can do with that object. Also, the font size seems to be kind of unfriendly – small and a little bit cramped(I know one can resolve this with zoom on the page). I will probably get used to the documentation, but in the meantime I will crave for Java documentation.
Even though, I knew it is not a pure object oriented programming language, is it still funny to white something “outside an object”, but this did not bother me at all, on the contrary, I found it really easy to get started writing code.
Another thing I really like the command line interpretor, that can be run from the command line. Having this is really helpful for the people that have their first contacts with Python. One can actually test something before adding it to a program.
That’s all for now, but I will keep posting further impressions :).