JNDI Lookup for Spring Portlet Wars

A new tag is available to help do your JNDI lookups in Spring portlet wars deployed to Liferay 7

Introduction

You may have seen my blog Setting Up JNDI in Liferay 7.4 which I posted to explain how to do a JNDI lookup.

The code works, I assure you, but there's one group of developers that blog didn't serve: Spring Portlet Developers.

Whether you are developing using PortletMVC4Spring and Spring 5, or you are developing using Spring Portlet MVC under an older version of Spring, JNDI lookups are still a pain.

If you have done JNDI lookups in regular Spring, you know that they provide a really useful tag for the context XML files: the <jee:jndi-lookup /> tag.

This tag is so easy to use. You define the bean name that the object found in the JNDI lookup will be, and the implementation will complete the JNDI lookup for you and put the bean into the context!

Up until now, though, this super-simple tag could not be used within Liferay.

This is no longer true...

The New Liferay Spring Tag

Yes, you read that right, there's a new Liferay Spring tag that can be used in Spring portlet wars.

The new <lrjee:jndi-lookup /> tag is exactly the same syntax as the old tag, just with a new namespace.

Your Spring context xml declaration needs to change slightly, so you'll be using the new namespace as such:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:lrjee="http://www.liferay.com/schema/lrjee" 
  xmlns:context="http://www.springframework.org/schema/context" 
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.liferay.com/schema/lrjee
      http://www.liferay.com/schema/lrjee/liferay-jee.xsd
    http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd">

With this new namespace in place, change all of your <jee:jndi-lookup /> tags to <lrjee:jndi-lookup /> tags:

<lrjee:jndi-lookup id="myDataSource" 
  jndi-name="java:comp/env/jdbc/TestDB" resource-ref="true"/>`

This new tag is actually just a simple extension of Spring's implementation. Therefore the core functionality isn't changed at all, but it does know how to ensure the class loader is correctly switched to the proper Portal class loader before completing the JNDI lookup.

Spring Java Configuration Support

If you're using Spring's java configuration support using annotations, there is support in this library to help with that too.

Your bean definition method will be:

@Bean(name = "myDataSource")
public DataSource dataSource(@Value("${jndi.name}") String jndiName) {
    PortalJndiDataSourceLookup lookup = new PortalJndiDataSourceLookup();
    return lookup.getDataSource(jndiName);
}

Like the new tag, the PortalJndiDataSourceLookup class extends Spring's JndiDataSourceLookup class. It uses all of the Spring logic, but it also tweaks it just a tiny bit to use the proper Portal class loader when doing the JNDI lookups.

Conclusion

Well, that's about it.

The whole project is open source and available on Github: https://github.com/dnebing/liferay-spring-jndi-lookup

Just clone the repo to your system, update the pom.xml properties for your version of Liferay and Spring, then you can build the jar and start using it in your projects.

Enjoy!

Blogs

Hello,

When attempting to implement this solution in my workspace, I'm getting the following XML Problem. "cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'lrjee:jndi-lookup'." My xmlns and schema locations are all correctly set to the liferay.com/schema paths. Any idea why it wouldn't be able to resolve this lookup?