Foren

Using a second JNDI database with a portlet

Nick Straguzzi, geändert vor 11 Jahren.

Using a second JNDI database with a portlet

New Member Beiträge: 15 Beitrittsdatum: 11.05.12 Neueste Beiträge
Folks:

Anyone have any idea about this one? I'm using Tomcat 6 and LR 6 EE SP2. I've created a Portlet plug-in which needs access to a separate MySQL database defined via JNDI and accessed via Hibernate. At runtime, the portlets in the plugin won't work; they throw an exception "Could not find datasource: jdbc/XXXX" followed by the dreaded "Name jdbc is not bound in this Context".

Again, this is NOT for the LR database. It's for a separate database that my portlets need to access. One would think there is something wrong with my configuration, but, here's the kicker: I've set up both the LR database and my second database via JNDI, and the Liferay database works perfectly.. I'm going crazy trying to figure out why one works and the other doesn't. The essentials:

In Tomcat's context.xml I define both JNDI resources....


<context>
	<resource name="jdbc/LiferayDB" auth="Container" type="javax.sql.DataSource" maxActive="20" maxIdle="10" maxWait="5000" removeAbandoned="true" removeAbandonedTimeout="250" validationQuery="SELECT 1" username="user" password="pwd" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/lportal?useUnicode=true&amp;characterEncoding=UTF-8&amp;useFastDateParsing=false" /> 

	<resource name="jdbc/XXX" auth="Container" type="javax.sql.DataSource" maxActive="20" maxIdle="10" maxWait="5000" removeAbandoned="true" removeAbandonedTimeout="250" validationQuery="SELECT 1" username="user2" password="pwd2" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/myOtherDb" />
<context>
</context></context>


Obviously, in portal-ext.properties, I've configured LR to use the first datasource, jdbc/LiferayDB. It does this without any quarrel.

So now for the portlets. Inside my portlet project, I have a custom JAR file containing all of my Hibernate mappings (which, according to the Debug logs, all set up and parse perfectly). That JAR also contains hibernate.cfg.xml, which contains the following properties under the <session-factory>:


<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.datasource">jdbc/XXX</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>


Finally, within my app's META-INF folder, I have a context.xml file that includes:


<context>
  <resourcelink name="jdbc/XXX" global="jdbc/XXX" type="javax.sql.DataSource">
</resourcelink></context>


(And for the record, I have also tried copying the global <Resource> definition into the app's local context.xml, plus tried without any context.xml whatsoever.

The relevant stacktrace:


16:06:46,945 INFO  [NamingHelper:49] JNDI InitialContext properties:{}
16:06:46,947 ERROR [DatasourceConnectionProvider:78] Could not find datasource: jdbc/XXX
javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
	at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
	at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
	...

XXX-Hibernate session factory could not be created: org.hibernate.HibernateException: Could not find datasource
16:06:46,955 ERROR [render_portlet_jsp:154] javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
	at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
	at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
	at org.apache.naming.SelectorContext.lookup(SelectorContext.java:152)
	at javax.naming.InitialContext.lookup(InitialContext.java:392)
	at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:75)
	at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:143)
	at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:84)
	at org.hibernate.cfg.SettingsFactory.createConnectionProvider(SettingsFactory.java:459)
	at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:90)
	at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2863)
	at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2859)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1870)
	at my.local.HibernateUtil.<clinit>(HibernateUtil.java:23)
	at my.local.portlet.modulemenu.ModuleMenu.doView(ModuleMenu.java:67)
	at com.liferay.portal.kernel.portlet.LiferayPortlet.doDispatch(LiferayPortlet.java:205)
	at com.liferay.util.bridges.mvc.MVCPortlet.doDispatch(MVCPortlet.java:309)
	at javax.portlet.GenericPortlet.render(GenericPortlet.java:233)
	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:93)
</clinit>


Finally, my mental state:


AAAAARRRRRGGGGGGGGHHHHHHHHHH!!!!!!!!!!


Any help would be gleefully appreciated.

Regards,
Nick
thumbnail
Thomas Berg, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

Regular Member Beiträge: 131 Beitrittsdatum: 07.09.09 Neueste Beiträge
Try defining your resource in Tomcats server.xml (as a global resource):

tomcat/conf/server.xml:

  <globalnamingresources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase" />
	
    <resource name="jdbc/XXX" auth="Container" type="javax.sql.DataSource" maxActive="20" maxIdle="10" maxWait="5000" removeAbandoned="true" removeAbandonedTimeout="250" validationQuery="SELECT 1" username="user2" password="pwd2" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/myOtherDb" />	
  </globalnamingresources>


Put this in tomcat/conf/context.xml

<resourcelink name="jdbc/XXX" global="jdbc/XXX" type="javax.sql.DataSource"></resourcelink>


HTH

/ Thomas
Nick Straguzzi, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 15 Beitrittsdatum: 11.05.12 Neueste Beiträge
Thank you so much Thomas. That combination did the trick.

Best regards,
Nick
Huy Vo, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 3 Beitrittsdatum: 10.07.12 Neueste Beiträge
Follow the guidline but still failed
Could not find datasource: jdbc/XXX
, please help me solve this problem
note:I using liferay version 6.1 to development porlet with technical JSF+hibernte
thumbnail
Hitoshi Ozawa, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

Liferay Legend Beiträge: 7942 Beitrittsdatum: 24.03.10 Neueste Beiträge
Thomas's steps should work because I'm doing the same thing. What did you do?
Huy Vo, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 3 Beitrittsdatum: 10.07.12 Neueste Beiträge
Hi forum!
- I config JNDI step by step such as:
+ step 1: this tomcat forder add code in file ROOT.xml :
<resource name="jdbc/LiferayPool" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/lportal?useUnicode=true&amp;characterEncoding=UTF-8" username="root" password="root" maxActive="100" maxIdle="30" maxWait="10000" />

+step 2: add code below in file context.xml this forder tomcat
<resourcelink global="jdbc/LiferayPool" name="jdbc/LiferayPool" type="javax.sql.DataSource" />

+ step 3: add code in file portal-setup-wizard.properties
jdbc.default.jndi.name=jdbc/LiferayPool

+ step 4: this application porlet , i add code in file hibernate.cfg.xml
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.connection.datasource">jdbc/LiferayPool</property>
		<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
		<property name="hibernate.search.autoregister_listeners">false</property>		
		<property name="hibernate.current_session_context_class">thread</property>
		<property name="hibernate.connection.release_mode">auto</property>
		<property name="hibernate.show_sql">false</property>
		<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
		<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>

+ step 5: add code in file web.xml to application porlet (/docroot/WEB-INF/web.xml)
<resource-ref>
		<description>MySQL Datasource</description>
		<res-ref-name>
			jdbc/LiferayPool			
		</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>

- Then I restart server tomcat ok, build and deploy application porlet thorw error such as:
Initial SessionFactory creation failed.org.hibernate.service.jndi.JndiException: Unable to lookup JNDI name [jdbc/LiferayPool]
02:30:52,509 ERROR [PortletServlet:97] javax.portlet.PortletException: doBridgeDispatch failed:  error from Bridge in executing the request
javax.portlet.PortletException: doBridgeDispatch failed:  error from Bridge in executing the request



	at org.hibernate.service.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:68)
	at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:116)
	at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
	at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:223)
	at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:89)
	at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
	at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:71)
	at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2277)
	at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2273)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1742)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
	at com.liferay.faces.util.HibernateUtil.<clinit>(HibernateUtil.java:24)
	... 215 more
Caused by: javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
</clinit>

Please help me solve this problem,
Thank forum verry much!
Satya Narayana, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 2 Beitrittsdatum: 04.01.12 Neueste Beiträge
Have you given below entry in liferay portal-ext.properties in catalina home. If not give it, it works.

jdbc.default.jndi.name=jdbc/LiferayPool

There is ssecond approach, u can define your jndi resource in context.xml also and give refrence in ur web app like below

<resource-ref>
<description>MySQL Datasource</description>
<res-ref-name>jdbc/LiferayPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

Thanks,
Satya.
thumbnail
Sushil Kumar Saini, geändert vor 11 Jahren.

RE: Using a second JNDI database with a portlet

Regular Member Beiträge: 104 Beitrittsdatum: 27.07.11 Neueste Beiträge
Hi Huy,.... In the step 1. you have mentioned you are putting the configuration in the ROOT.xml. I think, it should go in the tomcat/conf/server.xml file.
Baogang Liu, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 10 Beitrittsdatum: 15.08.13 Neueste Beiträge
I meet the same problem when using "broadleaf commerce portlet demo site https://github.com/BroadleafCommerce/DemoSite-portlet" in liferay-portal-tomcat-6.2.0-ce-b1-20130801091812389.zip. I am not sure whether the root cause is from liferay or broadleaf. I also posted my question in broadleaf forum http://forum.broadleafcommerce.org/viewtopic.php?f=14&t=2108&p=5928.

Liferay logs:

"Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'blMergedDataSources' defined in resource loaded from byte array: Cannot resolve reference to bean 'webSecureDS' while setting bean property 'sourceMap' with key [TypedStringValue: value [jdbc/webSecure], target type ]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecureDS': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [jdbc/secure] is not bound in this Context. Unable to find .
Jose F. Fernandez, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 3 Beitrittsdatum: 31.07.13 Neueste Beiträge
I'm facing to issues with JNDI when Liferay is deployed in a Tomcat installation. If I undeploy Liferay I can see the JNDI datasources with Psi-probe, when Liferay is running, no JNDI datasources are shown, nor can be accesed. The root cause of the exception is:

Caused by: javax.naming.NameNotFoundException: Name java:comp/env/jdbc/aperte-reports is not bound in this Context

In my case, the problem is caused by the Liferay security manager, when overrides the context, all JNDI entries are lost.
If you have a plugin that enables the security manager, you will get that problem (mine was a carousel portlet), if you don't have such a portlet, with the default configuration, security manager will not be activated, so no problem!

Look for that text in your log:
14:24:29,225 INFO [localhost-startStop-1][PACLPolicyManager:90] Activating PACL policy manager
14:24:29,226 INFO [localhost-startStop-1][PACLPolicyManager:146] Overriding the current security manager to enable plugin security management
14:24:29,232 INFO [localhost-startStop-1][PortalSecurityManager:179] Overriding the initial context factory builder

If you have this, you will have problems with JNDI (no datasources will be shown by Psy-Probe, and other plugins that use JNDI such as Aperte Reports will stop to work)

If you have experienced these problems, you can disable Liferay security manager in portal-ext.properties, adding:
portal.security.manager.strategy=none

Hope will be helpfull for someone, I could not find a solution for this and have to debug code by hours after lot of time lost with configuration settings, trying different versions of Tomcat, etc. etc.

All is working now!!!
thumbnail
David H Nebinger, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

Liferay Legend Beiträge: 14915 Beitrittsdatum: 02.09.06 Neueste Beiträge
First of all, this thread was started long before the security manager came along, so your comment doesn't apply.

Back on point...

The security manager blocks the portlet from accessing things that it doesn't declare it is accessing. If you don't declare that you're going after something (such as a JNDI resource), it's not going to be able to.

The JNDI resources are not lost, you just have no access to them.

You can leave security manager enabled, just change your security-manager-enabled flag to "generate" and you'll be able to see the things that you need to enable to get to the resources.
Jose F. Fernandez, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 3 Beitrittsdatum: 31.07.13 Neueste Beiträge
Thank you David!!

As you can see, I'm replying to Baogang Liu, which commented a few days ago, not to the main question of the thread, wich gets responded and resolved a year ago...
Perhaps the other comments should be made ​​in a new thread, but they are here, so here I answered, sorry!

The problem I see with security manager is that once activated by a plugin, affects others, for example, in my case, Carousel Portlet plugin activates it, but it affects Aperte Reports, therefore, until you completely disable security manager, the plugin that looks JNDI and not employ security manager does not work.

The security manager is affecting too other webapps deployed, maybe that is the desired effect for you, but I want to be able to monitor the Tomcat instance and Datasources usage with Psi-probe, and if security manager is active, Psi-probe can't lookup JNDI datasources... what have I to configure to enable that?

Thank you!!!
Baogang Liu, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 10 Beitrittsdatum: 15.08.13 Neueste Beiträge
Thanks Jose and David. With below way, the jndi problem when using broadleaf in liferay-portal-tomcat-6.2.0-ce-b2-20130815141757862.zip disappear.

"disable Liferay security manager in portal-ext.properties, adding: portal.security.manager.strategy=none"

But for below things, can you give some advice:

1. If not set "portal.security.manager.strategy=none", there is no jndi problem when using broadleaf in liferay-portal-tomcat-6.2.0-ce-m3-20121226162932032.zip and liferay-portal-tomcat-6.1.1-ce-ga2-20120731132656558.zip. When using broadleaf in liferay-portal-tomcat-6.2.0-ce-m6-20130614143518319.zip, liferay-portal-tomcat-6.2.0-ce-b1-20130801091812389.zip or liferay-portal-tomcat-6.2.0-ce-b2-20130815141757862.zip, there is jndi problem.

Can we guess that the built-in example in liferay m6/b1/b2 enables liferay security manager but m3 not?

2. I searched 'security-manager-enabled' in all the xml/properties files in liferay b2 folder and lieray m3 folder with liferay build-in app and broadleaf deployed, and found "security-manager-enabled=false" in liferay-plugin-package_6_1_0.properties and liferay-plugin-package_6_2_0.properties under \liferay-portal-6.2.0-ce-xx\tomcat-7.0.40\Webapps\Root\Dtd\. I did not find a place where "security-manager-enabled=true".

I changed "false" to "generate", the jndi problem in liferay b2 still exist. The jndi problem in liferay m3 does not exist even if I does not change any config.

Where is the config which enables security-manager?

3. Using liferay-portal-tomcat-6.2.0-ce-b2-20130815141757862.zip, In the past I test several ways as mentioned in http://forum.broadleafcommerce.org/viewtopic.php?f=14&t=2108&p=5928, including define below content in tomcat/conf/web.xml and broadleaf-portlet's web.xml, did not solve the jndi problem.

<res-ref-name>jdbc/secure</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

So, when security manager is enabled, how an app refer to a jndi defined either in this app or in tomcat globa jindi? The much clear statement on this question should be Jose's description:

"The problem I see with security manager is that once activated by a plugin, affects others, for example, in my case, Carousel Portlet plugin activates it, but it affects Aperte Reports, therefore, until you completely disable security manager, the plugin that looks JNDI and not employ security manager does not work. '

The security manager is affecting too other webapps deployed, maybe that is the desired effect for you......"
Baogang Liu, geändert vor 10 Jahren.

RE: Using a second JNDI database with a portlet

New Member Beiträge: 10 Beitrittsdatum: 15.08.13 Neueste Beiträge
BTW, I submitted a new post in the past, as below link. No one reply in that post. So I wrote comments to that post to point to this post.

http://www.liferay.com/zh/community/forums/-/message_boards/message/27633700 NameNotFoundException' in m6/b1/b2 but NO problem in liferay 6.2.0m3