Connect Liferay 7.x with Oracle 11g2 external database - NullPointerException

1.3k Views Asked by At

First of all, I tried this with Liferay CE portal-7.1.0-GA1 and Liferay portal 7.0 CE GA1. I will explain details of my process. My portal-ext.properties (Liferay HOME folder) looks:

jdbc.ext.driverClassName=oracle.jdbc.OracleDriver
jdbc.ext.url=jdbc:oracle:thin:@localhost:1521:db
jdbc.ext.username=xxx
jdbc.ext.password=xxx

JARs:

- ojdbc14.jar (\liferay-portal-7.0-ce-ga1\tomcat-8.0.32\lib)
- liferay-portal-oracledb-support-1.0 and liferay-portal-oracledb-support-1.0-SNAPSHOT (liferay-portal-7.0-ce-ga1\tomcat-8.0.32\webapps\ROOT\WEB-INF\lib)
- added ext-spring.xml (\modules\DemoService\DemoService-service\build\resources\main\META-INF\spring)

Code for ext-spring.xml

    <?xml version="1.0"?>
    <beans default-destroy-method="destroy" default-init-method="afterPropertiesSet" xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
       <!--bean class="com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean"
          id="liferayDataSourceFactory">
          <property name="propertyPrefix" value="jdbc.ext." />
          <property name="properties">
              <props>
                  <prop key="custom.jndi.name">extDataSource</prop>
              </props>
          </property>
          </bean-->
       <bean class="com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean"
          id="liferayDataSourceFactory">
          <property name="propertyPrefix" value="jdbc.ext." />
       </bean>
       <bean
          class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"
          id="liferayDataSource">
          <property name="targetDataSource" ref="liferayDataSourceFactory" />
       </bean>
       <alias alias="extDataSource" name="liferayDataSource" />
    </beans> 

Getting this ERROR:

    00:10:31,259 ERROR [http-nio-8080-exec-5][render_portlet_jsp:131] null
    java.lang.NullPointerException
    at com.service.service.CountryLocalServiceUtil.getCountriesCount(CountryLocalServiceUtil.java:207)
    at com.demo.portlet.DemoPortlet.doView(DemoPortlet.java:39)
    at com.liferay.portal.kernel.portlet.LiferayPortlet.doDispatch(LiferayPortlet.java:302)
    at com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet.doDispatch(MVCPortlet.java:474)
    at javax.portlet.GenericPortlet.render(GenericPortlet.java:262)
    at com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet.render(MVCPortlet.java:294)
    at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:103)
    at com.liferay.portlet.ScriptDataPortletFilter.doFilter(ScriptDataPortletFilter.java:57)
    at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:100)
    at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:64)
    at com.liferay.portal.kernel.servlet.PortletServlet.service(PortletServlet.java:105)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at com.liferay.portal.osgi.web.servlet.context.helper.internal.ServletContextHelperRegistrationImpl$PortletServletWrapper.service(ServletContextHelperRegistrationImpl.java:507)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.eclipse.equinox.http.servlet.internal.registration.EndpointRegistration.service(EndpointRegistration.java:153)
    at org.eclipse.equinox.http.servlet.internal.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:50)
    at com.liferay.portal.osgi.web.servlet.context.helper.internal.ServletContextHelperRegistrationImpl$RestrictPortletServletRequestFilter.doFilter(ServletContextHelperRegistrationImpl.java:527)
    at org.eclipse.equinox.http.servlet.internal.registration.FilterRegistration.doFilter(FilterRegistration.java:121)
    at org.eclipse.equinox.http.servlet.internal.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:45)
    at org.eclipse.equinox.http.servlet.internal.servlet.ResponseStateHandler.processRequest(ResponseStateHandler.java:71) 

Country is entity in service.xml, after Gradle building service, CountryLocalServiceUtil is generated. If you are using Liferay 7, this is simple process of creating first app.

This is generated class, I can give the code:

  • From Portlet, I just called function CountryLocalServiceUtil.getCountriesCount()

  • this function in CountryLocalServiceUtil is:

    public static int getCountriesCount() {
        return getService().getCountriesCount(); 
    }
    
  • Open declaration is:

    CountryLocalService.java @Transactional(propagation = Propagation.SUPPORTS, 
                                            readOnly = true)
    public int getCountriesCount(); 
    
2

There are 2 best solutions below

1
On

You're running Liferay 7.x CE. Note that Liferay Community Edition (CE) does only support Open Source databases, e.g. no Oracle. There's a community provided add-on that adds support for Oracle and other commercial databases, but you don't indicate that you've installed it.

Thus, it seems that you're running Liferay from a supported database, and try to connect to Oracle in your "jdbc.ext" database. I'd expect this to not work, as it would require the servicebuilder mapping to Oracle, though they're not contained in CE.

You can always go with pure JDBC (e.g. no service builder), or try Antonio's plugin. Currently I'm only aware that it's out for 7.0, not for 7.1 (but I might be wrong here)

2
On

I am almost sure your problem is not the database but the service object not being available as your issue is no due getCountriesCount() but on getService().

As an experiment, try not using the *Util class but an OSGi @Reference for the service you want, this should rule out the database as an issue (at least for this matter). if you cannot get the service, you will probably find better troubleshooting information than a NPE being thrown in the *Util class.

As an example, in your component:

@Reference
private volatile CountryLocalService countryLocalService;

There are examples all over Liferay's source, like: https://github.com/liferay/liferay-portal/blob/180d89ccaa80b86e68402c73a1483cd9e1817311/modules/apps/export-import/export-import-resources-importer/src/main/java/com/liferay/exportimport/resources/importer/internal/util/ImporterFactory.java