Fóruns

Início » Liferay Portal » English » 3. Development

Visualização combinada Visão plana Exibição em árvore
Tópicos [ Anterior | Próximo ]
toggle
Adam Victor Nazareth Brandizzi
Getting Liferay Datasource in portlet not generated by Plugins SDK
16 de Março de 2012 06:36
Resposta

Adam Victor Nazareth Brandizzi

Ranking: Junior Member

Mensagens: 67

Data de entrada: 30 de Abril de 2010

Mensagens recentes

Hello, all.

First of all, I am using Liferay 6.0 EE SP2 in Tomcat 6.0.32.

I am trying to deploy some portlets in Liferay. These portlets are legacy code made by people who did not knew a lot about how Liferay works at the time and made, let us say, "amazing" decisions, such as to map Liferay Service Builder entity tables to new classes. These portlets are seamed by Spring and mapped to database by Hibernate. To avoid the annoying requirement of editing context.xml (which is tiresome, error prone, easily forgettable, makes the persistence layer slow as hell etc.) I provided the Liferay datasource as a new bean...

1    <bean id="liferayDataSource"
2        class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
3        <property name="targetDataSource">
4            <bean
5                class="com.liferay.portal.kernel.util.InfrastructureUtil"
6                factory-method="getDataSource" />
7        </property>
8    </bean>


...and used this new bean as the datasource of the Entity Manager Factory:

1    <bean id="entityManagerFactory"
2        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
3        <property name="dataSource" ref="liferayDataSource"/>
4        <property name="persistenceUnitName" value="liferay-db" />
5    </bean>


If I have the Liferay running and I deploy my portlets, it runs without problem because the Liferay resources are already available. The problem is, when I restart Liferay these portlets are loaded before the Liferay app going up, so the InfrastructureUtil class is not even loaded yet. The dependencies are not satisfied and the plugin cannot be loaded. This problem, however, does not happen when deploying portlets generated by Plugins SDK, even when they contain services generated by Service Builder.

So, how could I solve this problem? I wonder about two possible solutions:

  • Could I delay the loading of my portlet, in such a way it will be loaded after Liferay?
  • Could I delay the loading of the Spring context of the portlet, or make the context loading lazy / on-demand?


Are they viable? What other solutions could I try?
David H Nebinger
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
16 de Março de 2012 08:07
Resposta

David H Nebinger

Ranking: Liferay Legend

Mensagens: 6537

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

If you make the portlet that is failing have a required context dependency w/ the portlet that needs to go first (in liferay-plugin-package.properties file), Liferay will not load the portlet until the required one is loaded.
Adam Victor Nazareth Brandizzi
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
19 de Março de 2012 09:04
Resposta

Adam Victor Nazareth Brandizzi

Ranking: Junior Member

Mensagens: 67

Data de entrada: 30 de Abril de 2010

Mensagens recentes

David H Nebinger:
If you make the portlet that is failing have a required context dependency w/ the portlet that needs to go first (in liferay-plugin-package.properties file), Liferay will not load the portlet until the required one is loaded.


Thank you, David!

But how do I define such dependency? I just found about the recommended-deployment-context property, which does not seem to be the way to go. There is also the deployment-settings property, but I do not know how to fill it neither if it is the necessary one.

Thanks in advance!
Adam Victor Nazareth Brandizzi
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
19 de Março de 2012 15:15
Resposta

Adam Victor Nazareth Brandizzi

Ranking: Junior Member

Mensagens: 67

Data de entrada: 30 de Abril de 2010

Mensagens recentes

Apparently, I can define a dependency context using the required-deployment-contexts in liferay-plugin-package.properties. However, I just do not know what is the name of the Liferay context! Since it is the context root, should the name be empty? Or is named ROOT (which I doubt, because it did not work)?

Thanks in advance!
David H Nebinger
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
19 de Março de 2012 15:57
Resposta

David H Nebinger

Ranking: Liferay Legend

Mensagens: 6537

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

Empty for the ROOT context, otherwise the portlet context to get a portlet-specific instance.
Adam Victor Nazareth Brandizzi
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
20 de Março de 2012 10:16
Resposta

Adam Victor Nazareth Brandizzi

Ranking: Junior Member

Mensagens: 67

Data de entrada: 30 de Abril de 2010

Mensagens recentes

David H Nebinger:
Empty for the ROOT context, otherwise the portlet context to get a portlet-specific instance.


Thank you again, David

However, I have one more question: how could I set the property as the empty string in the liferay-plugin-package.properties? I have tried to do it in various ways; none worked:

1
2required-deployment-contexts=
3required-deployment-contexts=""
4required-deployment-contexts=   # Some spaces after the property name
5required-deployment-contexts=,     # I supposed the parser would consider the property as two empty strings separated by a comma


Is there a way to do it?

Thanks in advance again!
David H Nebinger
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
20 de Março de 2012 16:46
Resposta

David H Nebinger

Ranking: Liferay Legend

Mensagens: 6537

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

You don't need it. The Liferay context is guaranteed to be there, otherwise the portlets wouldn't work!

You only need to add to the required deployment context if the service builder stuff is specified in another portlet.

I.e. Portlet A has the service.xml and all of the appropriate service builder classes. Portlet B, which uses the service from Portlet A, should list Portlet A as a required deployment context.

But all portlets have an implied required deployment context on root.
Adam Victor Nazareth Brandizzi
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
21 de Março de 2012 05:48
Resposta

Adam Victor Nazareth Brandizzi

Ranking: Junior Member

Mensagens: 67

Data de entrada: 30 de Abril de 2010

Mensagens recentes

Hello again, David. Thank you for your help.

David H Nebinger:
You don't need it. The Liferay context is guaranteed to be there, otherwise the portlets wouldn't work!

You only need to add to the required deployment context if the service builder stuff is specified in another portlet.

I.e. Portlet A has the service.xml and all of the appropriate service builder classes. Portlet B, which uses the service from Portlet A, should list Portlet A as a required deployment context.

But all portlets have an implied required deployment context on root.


Unfortunately, this is not the case, at least at Liferay EE SP2. The context of my portlets are loading before the context of Liferay itself and so they not only are not working - they are preventing Tomcat of loading another contexts correctly as well. When my portlet loads, I got the log below (that is available, too, in the attached log file):

 1INFO: Deploying configuration descriptor [OMITTED-PORTLET-NAME]-portlet.xml
 22012-03-21 12:36:02,571 [main] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
 3org.springframework.beans.factory.BeanCreationException: Error creating bean with name
 4'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0'
 5defined in URL
 6[file:[PATH-TO-LIFERAY]/tomcat-6.0.32/temp/2-[OMITTED-PORTLET-NAME]-portlet/WEB-INF/classes/application-context-DAO.xml]:
 7Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException:
 8Error creating bean with name 'entityManagerFactory' defined in URL
 9[file:[PATH-TO-LIFERAY]/tomcat-6.0.32/temp/2-[OMITTED-PORTLET-NAME]-portlet/WEB-INF/classes/application-context-EntityManager.xml]:
10Cannot resolve reference to bean 'liferayDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liferayDataSource' defined in URL
11[file:[PATH-TO-LIFERAY]/tomcat-6.0.32/temp/2-[OMITTED-PORTLET-NAME]-portlet/WEB-INF/classes/application-context-Liferay.xml]:
12Cannot create inner bean 'com.liferay.portal.kernel.util.InfrastructureUtil#673dd208' of type [com.liferay.portal.kernel.util.InfrastructureUtil]
13while setting bean property 'targetDataSource'; nested exception is org.springframework.beans.factory.BeanCreationException:
14Error creating bean with name 'com.liferay.portal.kernel.util.InfrastructureUtil#673dd208' defined in URL
15[file:[PATH-TO-LIFERAY]/tomcat-6.0.32/temp/2-[OMITTED-PORTLET-NAME]-portlet/WEB-INF/classes/application-context-Liferay.xml]:
16Initialization of bean failed; nested exception is java.lang.NullPointerException


To add insult to injury, after the portlet fails to load I got this message:

121/03/2012 12:36:02 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
2GRAVE: The web application [/[OMITTED-PORTLET-NAME]-portlet] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.


So the JDBC driver is unloaded and the Liferay cannot go up because it depends upon this driver. However, as you already said, this does not happen when using portlets with their own services (and that, as a consequence, also use the Liferay data source).

Do you understand my point better now?

Anyway, thanks again.
Anexos: log (13,7k)
David H Nebinger
RE: Getting Liferay Datasource in portlet not generated by Plugins SDK
21 de Março de 2012 06:10
Resposta

David H Nebinger

Ranking: Liferay Legend

Mensagens: 6537

Data de entrada: 1 de Setembro de 2006

Mensagens recentes

The key is probably going to be found in the creation of a new service builder-based portlet. Those too will use the LiferayDataSource and their context gets loaded before the root context. I'm guessing if you imitate how the SB portlet creates the LiferayDataSource (check the src/META-INF/*.xml files), you'll find the key for instantiating the data source in your own portlet.