Because life has no try-catch

Leave a comment

Using ExifTool from Lightroom

A while ago I started testing Adobe Lightroom to process my photo’s and so far I’m pretty happy with it.

Even though it can handle some Exif metadata changes when exporting, I somehow missed the power of ExifTool and thus I started looking for a way to integrate it. There is somewhere on the internet a plugin, but you’ve got to pay for it so I looked further to find a cheaper way to do it.

And so I wrote myself a little export action script for Windows.

Step 1: find your export action folder

This is rather simple, by default it should be in C:\Users\<you>\AppData\Roaming\Adobe\Lightroom\Export Actions
However, if you’re a bit special, you can find it back by following the steps:

  1. Select a picture in your catalog and click the Export button (Library view)
  2. Scroll to the bottom of the screen that just opened and open the “After Export” dropdown and click on “Go To Export Action Folder Now”


Step 2: Download ExifTool and put the executable in this folder

It’s probably not the best place to store the executable, but this way you’ll also back-up the executable when backing up your settings. It’s best to rename the exiftool(-k).exe file to just exiftool.exe.


Step 3: Create the .bat

Create an empty text file and name it something like mySuperAction.bat  (name it like you want, just make sure it’s a .bat and not a .txt).

Past the following code in the .bat file:

@echo off
echo Processing Images
if not exist %1 exit
if exist %1 call "C:\Users\you\AppData\Roaming\Adobe\Lightroom\Export Actions\exiftool.exe" -overwrite_original -software=ExifTool %1
goto loop


Adapt the call to exiftool to your likings, this example will just overwrite the Software tag with ExifTool. Also don’t forget to update the path to exiftool in the script.


Have fun shopping.

Leave a comment

Eclipse RCP Dynamic popup menu

I do not have a lot of experience with the Eclipse Rich Client Platform (RCP), yet I was asked to create a dynamic submenu for an element in a JFace TreeView. The content of the submenu should be filled in depending on the selected object and a fixed menu item to allow a manual search should be added too. The complete menu should be hidden if the selected object already has a value for ‘myProperty’.
I’ve struggled for days to get this working, especially since most things on the internet refered to the MenuManager which didn’t work at all in my case.

Fortunately, after some trial and error I managed to set up the submenu using the standard plugin extensions.

The fixed command

First thing to define is the fixed command which will open a new dialog.

Under the org.eclipse.ui.commands extention point, add the following command definition

      <command defaultHandler="be.x.y.z.AddToHandler" id="be.x.y.z.addTo" name="Add to ..">

The corresponding handler class is fairly simple, it’ll just open a new dialog while passing the selected item to this dialog.

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.handlers.HandlerUtil;

public class AddToHandler implements IHandler {

  public void addHandlerListener(final IHandlerListener handlerListener) {

  public void dispose() {

  public Object execute(final ExecutionEvent event) throws ExecutionException {
    ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection();
    MyObject myObject = SelectionEval.singleton(selection, MyObject.class);
    MySearchDialog gds = new MySearchDialog(HandlerUtil.getActiveWorkbenchWindow(event).getShell(), myObject);
    return null;

  public boolean isEnabled() {
    return true; // set to true to make it always visible

  public boolean isHandled() {
    return true; // set to true to make it always visible

  public void removeHandlerListener(final IHandlerListener handlerListener) {


Testing the selected object

Next step is to define a property tester which will check if the selected object satisfies all conditions to show the menu.

The following property tester should be defined in the org.eclipse.core.expressions.propertyTesters extension point:

      <propertyTester class="be.x.y.z.addToPropertyTester" id="be.x.y.z.addToPropertyTester" namespace="be.x.y.z.addToPropertyTester" properties="myProperty" type="java.lang.Object">

The property tester itself is fairly simple and does nothing but a null-check

import org.eclipse.core.expressions.PropertyTester;
import be.x.y.z.MyObject;

public class AddToPropertyTester extends PropertyTester {

  public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
    if (property.equals("myProperty") && receiver instanceof MyObject) {
      MyObject myObject = (MyObject) receiver;
      return myObject.getMyProperty() == null;
    return false;


Adding menu items dynamically

Adding items using a dynamic menu requires an instance of a ContributionItem.

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.PlatformUI;

public class AddToContributionItem extends ContributionItem {

  public void fill(final Menu menu, final int index) {
    super.fill(menu, index);
    ISelection is = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getSelection();
    MyObject singleton = SelectionEval.singleton(is, MyObject.class);
    if (singleton == null) {

    Map<string, map<string,="" object="">> data = new TreeMap<>();
    // Some logic to fill in data

    int count = 0;
    for (Entry<string, map<string,="" object="">> entry : data.entrySet()) {
      if (++count > 15) {	// Limit number of items to 15
      MenuItem menuItem = new MenuItem(menu, SWT.NONE, index);
      menuItem.setData("OBJECT_DATA", entry.getValue().get("OBJECT_DATA"));	// you can store extra data here, which you can use in the selection listner
      menuItem.addSelectionListener(new SelectionAdapter() {

        public void widgetSelected(final SelectionEvent e) {
          MyData dO = (MyData) e.widget.getData("OBJECT_DATA");
          // Whatever you want to do


Glueing it all together

Last step is to glue everything together in an org.eclipse.ui.menus extension point:

      <menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any"> <!-- This is the menu contribution for the "add to" menu --></pre>
<menu id="be.x.y.z.addtomenu" label="Add to"> <!-- This is the menu item which <span class="hiddenSuggestion" pre="which " data-mce-bogus="1">contains</span> a sub menu -->

            	<!-- This is the dynamic part of the menu -->
            <command id="be.x.y.z.addToMenuContribution" label="..."></command>	<!-- This command will open the search dialog -->
                <!-- Use the isHandled() and isEnabled() method to show or hide this fixed menu item) -->

            	<!-- This is the fixed menu item which opens a new search dialog -->
            	<!-- Only show the menu if *selection*.count == *1* AND *selection*[O] instanceof MyObject AND *selection*[O] has no myProperty -->

                         <!-- Important, this is the property tester namespace + property -->

                  	<!-- Make sure we have selected only 1 single object -->



Disclaimer: I’m not an Eclipse RCP expert and even though this might work, it’s probably not the most efficient way to do this, especially because we’re binding it to popup:org.eclipse.ui.popup.any, however, it was to only way I could get this working in our somewhat bloated project.

Leave a comment

Automating JMX calls using JMXTerm

On the project I’m currently working on, we have a lot of tasks which are exposed through JMX and which we use very often. Some tasks need to be executed on a daily base, some even more often. As we all know, repetitive task are the ones we should automate and so I did.



Since I didn’t feel like writing another Java application just to call a Java application over JMX, I did some searches for a good command line JXM application and so I found JMXTerm. After fiddling around a bit, I wrote the following script which will connect to an Oracle XE database, retreive some data and use this data to call a JMX method which accepts a couple of parameters (many of which are just 0).



# prepare Oracle connection
. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh

# Find the exact bean name
BEAN="$(java -jar jmxterm-1.0-alpha4.jar s -l service:jmx:rmi:///jndi/rmi://localhost:2000/myjmx -n -i discover | grep "process=MyBeanProcess,type=MyProcess")"
echo $BEAN

# Variable I'll use to query the database
BPS="40706 42001 41038 40705 40186"
for bp in $BPS; do
        # send commands to sqlplus, spool results to a file output.out
        echo "SPOOL output.out;
        SPOOL OFF;
        exit;" | sqlplus sys/oracle@localhost as SYSDBA

        # extract the id's from the (human readable) output
        DATA=$(cat output.out | egrep "^[ ]{5}[0-9]+" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')

        # create an input script for jmxterm
        echo bean $BEAN > tmpJmxScript
        for x in $DATA; do
                echo run myJmxMethod 0 "$bp" 0 0 "${x}" 0 >> tmpJmxScript

        # connect to JMX server and execute the previously generated script
        java -jar jmxterm-1.0-alpha4.jar s -l service:jmx:rmi:///jndi/rmi://localhost:2000/myjmx -i tmpJmxScript -n

The tmpJmxScript file will look something like this

bean Processes:name=MyBeanProcess,Id=2,process=MyBeanProcess,type=MyProcess
run myJmxMethod 0 40186 0 0 15907 0
run myJmxMethod 0 40186 0 0 16340 0
run myJmxMethod 0 40186 0 0 16496 0

This script tells JMXTerm to use the bean ‘MyBeanProcess’ and execute the myJmxMethod JMX method using the parameters that follow.

Leave a comment

javax.xml.ws.soap.SOAPFaultException: Fault occurred while processing.

Last week, completely out of the blue I got faced with the following Soap exception:


2015-05-21 14:33:38,649 ERROR http-apr-8080-exec-4 [xxx.web.upload.generic.ExceptionHandler] Soap error
javax.xml.ws.soap.SOAPFaultException: Fault occurred while processing.
 at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
 at com.sun.proxy.$Proxy231.geefExcelLijst(Unknown Source)
 at xxx.web.upload.controller.UploadController.downloadBestand(UploadController.java:170)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
 at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
 at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:743)
 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:672)
 at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:82)
 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:919)
 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
 at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
 at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
 at xxx.web.beheer.shared.util.CspFilter.doFilter(CspFilter.java:50)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
 at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
 at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at xxx.security.openam.spring.security.OpenAMSSOLogoutFilter.doFilter(OpenAMSSOLogoutFilter.java:69)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
 at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
 at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
 at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
 at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
 at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
 at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2466)
 at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2455)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.cxf.binding.soap.SoapFault: Fault occurred while processing.
 at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
 at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46)
 at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
 at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:105)
 at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
 at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
 at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:771)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1604)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1489)
 at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1397)
 at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
 at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:644)
 at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
 at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:519)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:449)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:352)
 at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:304)
 at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
 at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
 ... 72 more

I didn’t matter whether I ran my calls through Soap-UI or through the application, I would always face this error. No clear solutions were available on the internet, except for a bunch of things you could try.

Eventually I started debugging my code again but instead of stopping once my webservice method returned, I kept going deeper, passing through a lot of unknown (decompiled) code untill I finally hit on a caught exception. It turned out that a newly added advice would convert the result to a JSON message for audit logging and this particular conversion would result in a StackOverflowException when the result contained binary data (through a javax.activation.DataHandler object).

So if you happen to have this error, you might also want to check out your aspects ;)

1 Comment

Simple Angular.JS 1.3 directive for Bootstrap tooltip

This is a very simple Angular.js (1.3) directive to add a Bootstrap 3 tooltip to any component.

  .directive('angularTooltip', function () {
    return {
      restrict: 'A',
      replace: false,
      scope: {
        tooltipPlacement: '=?',
        tooltip: '='
      compile: function compile( tElement, tAttributes ) {
        return function postLink( scope, element, attributes, controller ) {
          if (scope.tooltip !== '') {
            element.attr('data-toggle', 'tooltip');
            element.attr('data-placement', scope.tooltipPlacement || 'top');
            element.attr('title', scope.tooltip);
          scope.$watch('tooltip', function(newVal) {
            if (!element.attr('data-toggle')) {
              element.attr('data-toggle', 'tooltip');
              element.attr('data-placement', scope.tooltipPlacement || 'top');
              element.attr('title', scope.tooltip);
            element.attr('title', newVal);
            element.attr('data-original-title', newVal);

A simple example:

<button type="button" 
    class="btn btn-default" 
<input type="text" ng-model="title"></input>

Whatever you type, the tooltip will always be up to date.
Screenshot from 2015-05-05 19:41:37

Comes with no guarantee, but feel free to use it wherever you need it.

Leave a comment

J-ExifTool v0.0.9

Today I’ve released version 0.0.9 of J-ExifTool. This release doesn’t add new features, but it’s more reliable so I highly suggest the upgrade:

  • Maven support ! It’s not in a public repository (yet), but it’s one step closer to using J-ExifTool in a maven project ;)
  • Buffers are more reliable
  • Some tests are re-written

The new jar can be downloaded from BitBucket.

For the record only: v0.0.9 is commit a780161.

Leave a comment

J-ExifTool v0.0.8

Today I’ve released version 0.0.8 of J-ExifTool. This release adds new functionalities and provides some bug fixes:

  • #8: Delete all exif tags
  • #12: extract thumnail image
  • #15: it’s now possible to read exiftool path from environment variable
  • Improved reading out the command line buffer (no more lost/split/incorrect values, tests are more stable now)

Since release v0.0.5 you’ll need the Apache Commons Exec library in your classpath. I’ve added a new lib folder on BitBucket which includes this new library or you can download the new library from Apache.

The new jar can be downloaded from BitBucket.

For the record only: v0.0.8 is commit 2f4414f.


Get every new post delivered to your Inbox.

Join 46 other followers