Safe handling of ResourceResolvers

Just digging through my posts of the last years, I found that my last post to ResourceResolvers and JCR sessions is more than a year old. But unfortunately that does not mean, that this aspects seems widely understood; I still see a lot of improper use of these topics, when I review project code as part of my job.

But instead of explaining again and again, that you should never forget to close them, I want to introduce a different pattern, which can help you to avoid the “old pattern” of opening and closing completely. It’s a pattern, which encapsulates the opening and closing of a ResourceResolver, and your code is executed then as a Consumer or Function within. The ResourceResolver cannot leak, and you cannot do anything wrong. The only pre-requisite is Java 8, but that must not be a problem in 2020.

// does not return anything
public void withResourceResolver (Map<String,Object> authenticationInfo, Consumer<ResourceResolver> consumer) {
   try (ResourceResolver resolver = ResourceResolverFactory.getResourceResolver(authenticationInfo);) {
     consumer.accept (resolver);
   } catch (Exception e) {
     LOGGER.error ("Exception happend while opening ResourceResolver",e);
   }
}

Same is possible with a function to return a value

// return a value from the lambda
public <T> T withResourceResolver (Map<String,Object> authenticationInfo, Function<ResourceResolver,T> function, T defaultValue) {
   try (ResourceResolver resolver = ResourceResolverFactory.getResourceResolver(authenticationInfo);) {
     return function.apply(resolver);
   } catch (Exception e) {
     LOGGER.error ("Exception happend while opening ResourceResolver",e);
   }
   return defaultValue;
}

// convenience function
public <T> T withResourceResolver (Map<String,Object> authenticationInfo, Function<ResourceResolver,T> function) {
   return withSession(authenticationInfo,function, null;)
}

So if you are not familiar with the functional style of Java 8, some small examples how to use these methods:

Map<String,Object> authenticationInfo = …
withResourceResolver(authenticationInfo, resolver -> {
   Resource res = resolver.getResource("/");
   // do something more useful, but return nothing 
});

// return a value from the lambda 
Map<String,Object> authenticationInfo = …
String result = withResourceResolver(authenticationInfo, resolver -> {
   Resource res = resolver.getResource("/");
   return res.getPath();
});

As you can easily see, you don’t need to deal anymore with the lifecycle of ResourceResolvers anymore. And if your authenticationInfo map is always the same, you can even hardcode it within the withSession() methods, so the only parameter remains the consumer or the function.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.