Message Boards

JNDI service builder sample app fails

thumbnail
Pete Helgren, modified 4 Years ago.

JNDI service builder sample app fails

Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts
Still working every angle I can to get a JNDI -connected SB module to actually work in 7.3.  Originally I used the sample app as a model to modify my own SB module.  But when that failed, I decided to garb the code from the Github repo and build it directly with no modifications at all.  I get the same results as with my own code.  That is, when I deploy the SB modules, the -service module fails to connect using JNDI.  The code that is in Github and tagged as Branch:7.3  Presumably, someone tested this?   If so, I sure as heck can't get it to work.  It seems like such a common use case that I can't imagine that no one else has run into this.  Running LR 7.3 CE on Windows 10 using the Tomcat bundle.  Built using Liferay Developer Studio Version: 3.7.1.201910160309-ga2.  Here is the (lengthy) stack trace:

 2020-02-27 16:42:00.671 INFO  [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules][BundleStartStopLogger:39] STARTED com.liferay.blade.samples.jndiservicebuilder.api_1.0.0 [1124]
2020-02-27 16:42:16.844 WARN  [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules][ServiceComponentLocalServiceImpl:550] Auto upgrading REGION database to build number 11 is not supported for a production environment. Write an UpgradeStep to ensure data is upgraded correctly.
2020-02-27 16:42:16.870 WARN  [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules][ModuleApplicationContext:185] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSource' defined in URL [bundleentry://1125.fwk851109385/META-INF/spring/ext-spring.xml]: Cannot resolve reference to bean 'liferayDataSourceFactory' while setting bean property 'targetDataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSourceFactory' defined in URL [bundleentry://1125.fwk851109385/META-INF/spring/ext-spring.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
2020-02-27 16:42:16.874 ERROR [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules][LogService:93] [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules] Invocation of 'start' failed. 
java.lang.Exception: Unable to start com.liferay.blade.samples.jndiservicebuilder.service
    at com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextRegistrator.start(ModuleApplicationContextRegistrator.java:107)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.felix.dm.impl.InvocationUtil.invokeMethod(InvocationUtil.java:157)
    at org.apache.felix.dm.impl.InvocationUtil.invokeCallbackMethod(InvocationUtil.java:112)
    at org.apache.felix.dm.impl.ComponentImpl.invokeCallbackMethod(ComponentImpl.java:638)
    at org.apache.felix.dm.impl.ComponentImpl.invoke(ComponentImpl.java:1783)
    at org.apache.felix.dm.impl.ComponentImpl.invokeStart(ComponentImpl.java:1281)
    at org.apache.felix.dm.impl.ComponentImpl.performTransition(ComponentImpl.java:1232)
    at org.apache.felix.dm.impl.ComponentImpl.handleChange(ComponentImpl.java:1166)
    at org.apache.felix.dm.impl.ComponentImpl.lambda$start$2(ComponentImpl.java:502)
    at org.apache.felix.dm.impl.SerialExecutor.runTask(SerialExecutor.java:138)
    at org.apache.felix.dm.impl.SerialExecutor.runTasks(SerialExecutor.java:120)
    at org.apache.felix.dm.impl.SerialExecutor.execute(SerialExecutor.java:86)
    at org.apache.felix.dm.impl.SerialExecutor.execute(SerialExecutor.java:105)
    at org.apache.felix.dm.impl.ComponentImpl.start(ComponentImpl.java:500)
    at org.apache.felix.dm.impl.ComponentScheduler.add(ComponentScheduler.java:69)
    at org.apache.felix.dm.DependencyManager.add(DependencyManager.java:141)
    at com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextExtender$ModuleApplicationContextExtension.start(ModuleApplicationContextExtender.java:150)
    at com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextExtender.addingBundle(ModuleApplicationContextExtender.java:76)
    at com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextExtender.addingBundle(ModuleApplicationContextExtender.java:55)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:475)
    at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:1)
    at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
    at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
    at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:450)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:908)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
    at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEventPrivileged(EquinoxEventPublisher.java:230)
    at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:137)
    at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:129)
    at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor.publishModuleEvent(EquinoxContainerAdaptor.java:191)
    at org.eclipse.osgi.container.Module.publishEvent(Module.java:476)
    at org.eclipse.osgi.container.Module.doStart(Module.java:578)
    at org.eclipse.osgi.container.Module.start(Module.java:449)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:428)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1297)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1270)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:524)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:369)
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:320)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSource' defined in URL [bundleentry://1125.fwk851109385/META-INF/spring/ext-spring.xml]: Cannot resolve reference to bean 'liferayDataSourceFactory' while setting bean property 'targetDataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSourceFactory' defined in URL [bundleentry://1125.fwk851109385/META-INF/spring/ext-spring.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1699)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
    at com.liferay.portal.spring.aop.AopConfigurableApplicationContextConfigurator$AopBeanFactoryPostProcessor._getPlatformTransactionManager(AopConfigurableApplicationContextConfigurator.java:189)
    at com.liferay.portal.spring.aop.AopConfigurableApplicationContextConfigurator$AopBeanFactoryPostProcessor.postProcessBeanFactory(AopConfigurableApplicationContextConfigurator.java:123)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:131)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532)
    at com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextRegistrator.start(ModuleApplicationContextRegistrator.java:89)
    ... 43 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSourceFactory' defined in URL [bundleentry://1125.fwk851109385/META-INF/spring/ext-spring.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
    ... 59 more
Caused by: java.lang.NullPointerException
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.liferay.portal.dao.jdbc.DataSourceFactoryImpl.testDatabaseClass(DataSourceFactoryImpl.java:546)
    at com.liferay.portal.dao.jdbc.DataSourceFactoryImpl.initDataSource(DataSourceFactoryImpl.java:128)
    at com.liferay.portal.kernel.dao.jdbc.DataSourceFactoryUtil.initDataSource(DataSourceFactoryUtil.java:39)
    at com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean.createInstance(DataSourceFactoryBean.java:48)
    at com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean.createInstance(DataSourceFactoryBean.java:30)
    at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:142)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792)
    ... 66 more
2020-02-27 16:42:16.876 INFO  [fileinstall-E:/Liferay/liferay-ce-portal-7.3.0-ga1/osgi/modules][BundleStartStopLogger:39] STARTED com.liferay.blade.samples.jndiservicebuilder.service_1.0.0 [1125]


I have tried as many things as I can think of but I would have thought that published sample code would work. So, I am stuck. Is there anyone in the Liferay fold that could check the sample code for validity as a use case in 7.3?   It appears the code has been recently updated but I'll be darned if I can get it to work.
thumbnail
David H Nebinger, modified 4 Years ago.

RE: JNDI service builder sample app fails

Liferay Legend Posts: 14919 Join Date: 9/2/06 Recent Posts
Hey, Pete...


So you can't just use Spring's JNDI context lookup mechanism because it has to run within the Portal's class loader during the JNDI lookup.

Normally I use an extension of Spring's factory class to set the ThreadContextClassLoader to the portal's class loader, do the JNDI lookup, then restore the TCCL on the way out of the lookup.
Grant Wagner, modified 4 Years ago.

RE: JNDI service builder sample app fails

New Member Posts: 3 Join Date: 3/12/20 Recent Posts
Pete,Did you ever get this resolved?We are in the progress of upgrading from Liferay DXP 7.0 to 7.2, and every SB -service module we build causes the error you quoted.We are using Liferay Developer Studio 3.8.0, trying to deploy to Liferay DXP 7.2 Fix Pack 4 w/ Tomcat 9.0.31.David's explanation doesn't seem to align with what we're seeing as these same SB -service modules when built from LDS 3.6.2 and deployed to DXP 7.0 Fix Pack 81 work fine.
Grant Wagner, modified 4 Years ago.

RE: JNDI service builder sample app fails

New Member Posts: 3 Join Date: 3/12/20 Recent Posts
A quick update...

We resolved the original problem by following the instructions here:

https://portal.liferay.dev/docs/7-1/tutorials/-/knowledge_base/t/connecting-service-builder-to-external-databases#step-2-create-a-spring-bean-that-points-to-the-data-source

The important step is to put ext-spring.xml in [src/main/resources/META-INF/spring/parent] rather than [src/main/resources/META-INF/spring].

However, now we're getting:

Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy] for bean with name "liferayDataSource" defined in URL [bundleentry://1113.fwk1778902730/META-INF/spring/parent/ext-spring.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy cannot be found by [service]

Yes we've tried adding spring to build.gradle. Makes no difference since the ClassNotFound happens during deployment, not build.

Hope this information helps someone.
thumbnail
Pete Helgren, modified 4 Years ago.

RE: JNDI service builder sample app fails

Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts
This has been really disappointing.  Seems like using JNDI within an SB module would be a standard way of handling DB connections so the fact that the code is IN 7.3 and isn't flagged as deprecated and the documentation *seems* to point to the fact that it would work and yet it doesn't is just a hassle.  I am currently stuck at 7.1 after getting the go ahead to move forward with Liferay as our web serving platform and now I can't move forward.  It may scuttle the whole project.Working code, solid examples and good documentation are essentials.  When it comes to JNDI and 7.3 (or 7.2 for that matter) I got nuthin....
khaja moinuddin, modified 3 Years ago.

RE: JNDI service builder sample app fails

New Member Posts: 17 Join Date: 12/4/15 Recent Posts
Even we are facing the same issue any one managed to fix the issue ?
Grant Wagner, modified 3 Years ago.

RE: JNDI service builder sample app fails

New Member Posts: 3 Join Date: 3/12/20 Recent Posts
<p>We are waiting until we can install the Liferay Workspace (which will not install in our environment due to network drive mapping issues which Liferay has been investigating for 3 months).</p>

<p>However, I *think* it might have something to do with needing something like Import-Package: !org.springframework.jdbc.datasource.*, * in bnd.bnd, but until we get the Liferay Workspace installed we can&#39;t really trouble-shoot things.</p>

<p>Sorry I couldn&#39;t be more help.</p>
thumbnail
Pete Helgren, modified 3 Years ago.

RE: JNDI service builder sample app fails

Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts
I had a couple of different threads going.  The approach I took (NOT using JNDI)  is documented in the other thread:

https://liferay.dev/forums/-/message_boards/message/118600322#_com_liferay_message_boards_web_portlet_MBPortlet_message_119094905

(I hope that renders OK...)   It took a little work, and the approach isn't as slick as it was with JNDI, but I FINALLY have SB modules connecting to multiple, external resources.  I took the portal-ext.properties approach because it was the ONLY way to get a SB module connected to something other than the Liferay DB
thumbnail
Pete Helgren, modified 3 Years ago.

RE: JNDI service builder sample app fails (Answer)

Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts
SOLVED!  FINALLY!!!

This has been a very frustrating journey and I have finally solved the issue and it was drop, dead, simple.  Prior to 7.3.2  I used the "classic" JNDI configuration where you have "resource" entries in context.xml and server.xml.  When that stopped working I resorted to using the portal-ext.properties file approach.  What I lost was the connection pooling and all the other levers and knobs to tweak the DB connection settings that the JNDI approach handles.  So I decided to try ONE LAST TIME.  This time I actually dug into the code and noticed this little tidbit in the DataSourceFactoryImpl.java file:
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;DataSource&nbsp;initDataSource(Properties&nbsp;properties)&nbsp;throws&nbsp;Exception&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;jndiName&nbsp;=&nbsp;properties.getProperty("jndi.name");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(Validator.isNotNull(jndiName))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;currentThread&nbsp;=&nbsp;Thread.currentThread();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader&nbsp;classLoader&nbsp;=&nbsp;currentThread.getContextClassLoader();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentThread.setContextClassLoader(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PortalClassLoaderUtil.getClassLoader());

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;jndiEnvironmentProperties&nbsp;=&nbsp;PropsUtil.getProperties(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropsKeys.JNDI_ENVIRONMENT,&nbsp;true);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Context&nbsp;context&nbsp;=&nbsp;new&nbsp;InitialContext(jndiEnvironmentProperties);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(DataSource)JNDIUtil.lookup(context,&nbsp;jndiName);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;exception)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_log.error("Unable&nbsp;to&nbsp;lookup&nbsp;"&nbsp;+&nbsp;jndiName,&nbsp;exception);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentThread.setContextClassLoader(classLoader);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;
That basically told me that a properties file entry with the prefix of my DS reference plus "jndi.name" would lookup the JNDI context for me!  Voila!  So if you basically follow the tutorial for: https://help.liferay.com/hc/en-us/articles/360032978871-Connecting-the-Data-Source-Using-a-DataSourceProvider  all you need to do is to add ONE entry instead of four:

jdbc.ext.jndi.name=jdbc/MyJNDIContextName   -->  This points to the value you used for your JNDI content in context.xml and server.xml.  DONE!  Very simple.

Man!  I hope this helps someone else because it has been a HUGE headache for me in moving to 7.3.2