Fórum

Using Service-Builder Entities without creating Database Tables

thumbnail
Prakash Khanchandani, modificado 12 Anos atrás.

Using Service-Builder Entities without creating Database Tables

Expert Postagens: 329 Data de Entrada: 10/02/11 Postagens Recentes
The subject may sound like the thread here: Service Builder with non-DB data source , but its not the same.

Here is how it differs:
When I create the entities in service.xml without any <column> tag, it generates all the localService and service classes but it does not generate any model.

My question is how do I generate an entity with all the properties specified in the service.xml but not create a database table when I deploy the portlet.

I want to use the entity as a return type to my method calls, and also will use it as a web-service returning the entity.

Is it possible?

So in short the question could be asked like this:
Can I build a web-service using service-builder which returns a custom object/entity instead of the model entity?
or
Can I build a web-service using service-builder which returns the model entity but does not create a Database table for the entity?

Your help will be very much appreciated.

Thanks for helping.
thumbnail
Prakash Khanchandani, modificado 12 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Expert Postagens: 329 Data de Entrada: 10/02/11 Postagens Recentes
Will this be possible?

Any suggestions or any hints in this direction?

Thank you
thumbnail
Gerald Rubin, modificado 12 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables (Resposta)

Junior Member Postagens: 59 Data de Entrada: 23/10/11 Postagens Recentes
You may have to build the table once, but you can delete them and avoid re-building them when you update service.xml.

After the first deploy, look at the servicecomponent table in your database. You will find a row for your service's namespace and a buildNumber. It will most likely be 1.

Open service.properties under docroot/WEB-INF/src and make sure that this is at the top
    #
    # Specify where to get the overridden properties. Updates should not be made
    # on this file but on the overridden version of this file.
    #
    include-and-override=${base.path}/service-ext.properties



It might be there already. If you don't have a service-ext.properties file just above service.properties in Package Explorer (Eclipse assumed), create one. Put in one line:
    build.number=1


Never increment it and, for good measure, keep build.number=1 in service.properties.

You should be good.
thumbnail
Prakash Khanchandani, modificado 12 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Expert Postagens: 329 Data de Entrada: 10/02/11 Postagens Recentes
Thanks a lot Gerald.

It works.

It seems the right way to go, but just a little question: For the deployments after this, would the updates work correctly? (I suppose they should, not encountered any problems till now, but still just to confirm)

Thanks again.
thumbnail
Gerald Rubin, modificado 12 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 59 Data de Entrada: 23/10/11 Postagens Recentes
Yes, the updates would work correctly. If you're using the service.jar from any other portlets, you'll want to deploy, stop Tomcat, move the xxx-service.jar from the /lib folder in your portlet to tomcat/lib/ext and add it in that location to all build classpaths from other portlets. Then, of course, restart Tomcat.

See, one Junior Member can help another!
thumbnail
solomon merkebu, modificado 7 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

New Member Postagens: 2 Data de Entrada: 15/02/16 Postagens Recentes
Gerald Rubin:
Yes, the updates would work correctly. If you're using the service.jar from any other portlets, you'll want to deploy, stop Tomcat, move the xxx-service.jar from the /lib folder in your portlet to tomcat/lib/ext and add it in that location to all build classpaths from other portlets. Then, of course, restart Tomcat.

See, one Junior Member can help another!

Documentation: Advanced Liferay Configuration
Couple of months ago I had to create Database View with LR (Liferay) using service builder. Searching on web I couldn’t find any tutorial or solution. LR don’t know anything like views of databases. After some night work I came to know that it is very easy, as View is just an entity in DB so by fooling (not actually fooling) service builder that our View is an entity you can very easily create service classes and other functionalities of View via service builder.

Trick is to just create an entity in service.xml instead of view, run your service builder, which will create all necessary classes for that entity (actually view), run your LR project which will create this entity / view in actual DB. After this delete the created entity and run manual sql to create view of same name as it was entity in LR. Now LR will consider this view as an entity and enjoy your rest of work.

Let’s have a simple but practical example in which there will be two entities and one view.

I am using LR 6.1 JSF for front end, tomcat 7, and MySQL as DB for this example.

Two entities,

Citizen (Citizen_Id, First_Name, Middle_Name, Last_Name, Mobile, Marital_Status_Id) where Marital_Status_Id is you can say the FK from Marital_Status entity, I am handling FK at front end in this example.

Marital_Status (Marital_Status_Id, Marital_Status)

and one View is our discussion point

Citizen_View (Citizen_Id, Complete_Name, Martal_Status) where Complete_Name will be concatenation of First_Name, Middle_Name and Last_Name of Citizen entity where as Marital_Status will come from Marital_Status entity.

Step 1:

Create service.xml via service builder. Here is the complete service.xml for our example.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE service-builder PUBLIC "-LiferayDTD Service Builder 6.1.0EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">

<service-builder package-path="com.view.test">

<author>ayyazk</author>

<namespace>ABC</namespace>

<entity name="Citizen" local-service="true" remote-service="true"> <!-- PK fields --> <column name="Citizen_Id" type="long" primary="true" /> <column name="First_Name" type="String" /> <column name="Middle_Name" type="String" /> <column name="Last_Name" type="String" /> <column name="Mobile" type="String" /> <column name="Marital_Status_Id" type="long"/> </entity>

<entity name="Marital_Status" local-service="true" remote-service="true">

<!-- PK fields --> <column name="Marital_Status_Id" type="long" primary="true" /> <column name="Marital_Status" type="String" /> </entity> <entity name="Citizen_View" local-service="true" remote-service="true"> <!-- PK fields --> <column name="Citizen_Id" type="long" primary="true" /> <column name="Complete_Name" type="String" /> <column name="Marital_Status" type="String" /> </entity>

</service-builder>

Run your service builder, which will create all service classes for our entities.

Step 2:

Run your server, upon successful run LR will create our desired entities in Database.

Step 3:

Here is the tricky point, drop your entity named “Citizen_View”, and run following sql command in your database.

CREATE VIEW abc_Citizen_View AS

SELECT Citizen_Id , CONCAT (First_Name, ' ' , Middle_Name, ' ' , Last_Name) Complete_Name , m.Marital_status FROM abc_citizen c INNER JOIN abc_marital_status m ON( m.Marital_Status_ID = c.Marital_Status_ID );

Which will create View with the same name as was your entity in DB, if you will not delete the entity first this command will give you error like entity already exist with same name.

Step 4:

Populate your two entities, “Citizen” and “Marital_Status”, you will see that your view is already populated according to entries of above two tables.

Done, just code your required logic as data is available in view

Following is code proof which works with our example if we run our portlet.



public String getViewData() throws SystemException, PortalException{

List<Citizen_View> viewList = Citizen_ViewLocalServiceUtil.getCitizen_Views (0, Citizen_ViewLocalServiceUtil.getCitizen_ViewsCount()); System.out.println("Size of Citizen_View List "+viewList.size()); for (Citizen_View citizen_View : viewList) { System.out.println("Name "+citizen_View.getComplete_Name()); System.out.println("Marital Status: "+ citizen_View.getMarital_Status()); } / another way/ Citizen_View view = Citizen_ViewLocalServiceUtil.getCitizen_View(1); System.out.println(""); System.out.println("Name "+view.getComplete_Name()); System.out.println("Marital Status: "+ view.getMarital_Status()); return "";

}

If you feel any problem regarding above concepts feel free to ask.
thumbnail
David H Nebinger, modificado 7 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
solomon Merkebu Adamu:
Trick is to just create an entity in service.xml instead of view, run your service builder, which will create all necessary classes for that entity (actually view), run your LR project which will create this entity / view in actual DB. After this delete the created entity and run manual sql to create view of same name as it was entity in LR. Now LR will consider this view as an entity and enjoy your rest of work.


Oh, Merkebu you're making this a lot harder than it has to be...

First, SB code will not create tables if they already exist. So if you had just started by creating your view before deploying, everything would have been fine.

SB/Hibernate don't really do anything different when querying from views vs tables as the underlying JDBC doesn't really treat them differently either.

As long as you pre-create the view, SB will happily query from the view w/o ever creating a table.

P.S. in your <entity /> element you can add the db-name attribute to map directly to a view name in the database so it won't take on the default Liferay namespaced table.





Come meet me at the LSNA!
Remis Baima, modificado 11 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

New Member Postagens: 8 Data de Entrada: 05/11/10 Postagens Recentes
We have a similar use case:
- We have N plugins that need the same POJO (e.g. Foo).
- So we simply created the POJO and copy-and-paste to all N plugins.
- But we thought: "hey... this is a lot of duplicated code" (i.e. very bad :-)
- We had the idea to use the ServiceBuilder (SB ) to create this POJO in a base plugin and reference it in all other N plugins that needed to use this POJO (similar to what we do with SB shared services).
- So we defined the POJO in service.xml and let SB auto-generate the POJO for us.
- The problem is that SB always generates a DB table and we do not need/want one.
- This is why we need a way to avoid the SB to generate the DB tables.

Then we found a way to trick SB in not creating the DB tables, but we decided to not use it as it is not an official feature supported by Liferay (we use the EE version) and we want to avoid problems in a future migration.
But anyway, the trick is:
- In service.xml specify a data-source for your entity e.g.:
<entity name="Foo" local-service="false" remote-service="false" data-source="no_data_source">
<column name="fooId" type="long" primary="true" />
<column name="companyId" type="long" />
<column name="userId" type="long" />
<column name="userName" type="String" />
</entity>

-In your ext-spring.xml add:
<bean id="no_data_source" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<ref bean="liferayDataSource" />
</property>
</bean>
thumbnail
David H Nebinger, modificado 11 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Actually, I think another alternative (aside from the lazy data source), would be to set up a datasource using HSQL or some other in-memory-only data source.

That way, in case some unknowning developer actually calls one of the CRUD routines, you wouldn't have to worry about the table actually getting created. And if the table wasn't created, you're still able to use your entities as you had started.
thumbnail
Riccardo Rotondo, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 29 Data de Entrada: 11/06/10 Postagens Recentes
Dear all,

the problem I'm facing is similar. I'm trying to write a method returning a complex object. For complex object I mean an object that represents two entities. For this reasons I created a fake entity referring to the existing one.


<entity name="File" local-service="true" remote-service="false">
        <column name="fileId" type="long" primary="true" id-type="increment" />
        <column name="name" type="String" />
        <column name="userId" type="long" />
        <column name="size" type="long" />
        <column name="date" type="Date" />  
        <column name="virtualPaths" type="Collection" entity="VirtualPath" mapping-table="Files_VirtualPaths" />  
        <column name="storageURLs" type="Collection" entity="StorageURLs" mapping-key="fileId" />  
        <column name="tags" type="Collection" entity="Tag" mapping-table="Files_Tags" /> 
        <order by="asc">
            <order-column name="name" />
        </order>
    </entity>

<entity name="VirtualPath" local-service="true" remote-service="false">
        <column name="vpId" type="long" primary="true" id-type="increment" />
        <column name="vp" type="String" />
        <column name="userId" type="long" />
        <column name="date" type="Date" />  
        <column name="files" type="Collection" entity="File" mapping-table="Files_VirtualPaths" />
        <order by="asc">
            <order-column name="userId" />
            <order-column name="vp" />
        </order>   
        <finder name="VP_userId" return-type="VirtualPath">
            <finder-column name="vp" />
            <finder-column name="userId" />
        </finder>
    </entity>

<entity name="DirectoryElement" local-service="true" remote-service="false" data-source="noDataSource">
        <column name="id" type="long" primary="true" />
        <column name="VirutalPathElement" type="Collection" entity="VirtualPath" mapping-key="vpId" />
	<column name="FileElement" type="Collection" entity="File" mapping-table="VirtualPath_DirectoryElement_noDataSource" />
	</entity>



That's becuase I want File and VirtualPath mapped on the database, DirectoryElement not. The build services works properly. The deploy no. Probably because I didn't define any "noDataSource" in the ext-spring.xml. By the way where I should create it? In the same folder of service.xml??

Plus, I liked so much David suggestion of use a memory-only-data source. Please could you be more explicit about that? How should I define it?

Thank you very much for your precious help.

Regards,

Riccardo
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Riccardo Rotondo:
Probably because I didn't define any "noDataSource" in the ext-spring.xml. By the way where I should create it? In the same folder of service.xml??


Nope, it goes into the META-INF\ext-spring.xml and follows the following pattern:

<bean id="noDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
  <property name="targetDataSource" ref="liferayDataSource" />
</bean>


Plus, I liked so much David suggestion of use a memory-only-data source. Please could you be more explicit about that? How should I define it?


Just like you'd define any datasource. You can use HSQL for the driver, an appropriate jdbc url, etc. These would also be defined in META-INF/ext-spring.xml, but along with the data source definition you also need to define a com.liferay.portal.spring.hibernate.PortletHibernateConfiguration bean and a com.liferay.portal.dao.orm.hibernate.PortletSessionFactoryImpl bean.
thumbnail
Riccardo Rotondo, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 29 Data de Entrada: 11/06/10 Postagens Recentes
Dear David,

thank you for your quick helpful reply.

Right now I'm facing another issue. Despite fake-entities works file with "simple" type (such as long or string) I got sever errors in building the service once I specify a collection as follows:


<column name="VirutalPathElement" type="Collection" entity="VirtualPath" mapping-table="VirtualPath_DirectoryElement_noDataSource" />


Once I specify type Collection the built of the VirtualPath and other entities fail.


Method public java.util.List com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(java.lang.String) throws java.io.IOException threw an exception when invoked on com.liferay.portal.tools.servicebuilder.ServiceBuilder@5b09062e
The problematic instruction:
----------
==&gt; list serviceBuilder.getMappingEntities(column.mappingTable) as mapColumn [on line 260, column 41 in com/liferay/portal/tools/servicebuilder/dependencies/model_impl.ftl]
----------

Java backtrace for programmers:
----------
freemarker.template.TemplateModelException: Method public java.util.List com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(java.lang.String) throws java.io.IOException threw an exception when invoked on com.liferay.portal.tools.servicebuilder.ServiceBuilder@5b09062e
	at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:130)
	at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
	at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
	at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.Environment.visit(Environment.java:310)
	at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:179)
	at freemarker.core.Environment.visit(Environment.java:428)
	at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:221)
	at freemarker.core.Environment.process(Environment.java:199)
	at freemarker.template.Template.process(Template.java:237)
	at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:47)
	at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:37)
	at com.liferay.portal.tools.servicebuilder.ServiceBuilder._processTemplate(ServiceBuilder.java:4983)
	at com.liferay.portal.tools.servicebuilder.ServiceBuilder._createModelImpl(ServiceBuilder.java:2293)
	at com.liferay.portal.tools.servicebuilder.ServiceBuilder.<init>(ServiceBuilder.java:671)
	at com.liferay.portal.tools.servicebuilder.ServiceBuilder.main(ServiceBuilder.java:151)
Caused by: java.lang.NullPointerException
	at com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(ServiceBuilder.java:1048)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:866)
	at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:106)
	... 27 more
</init>


Is there any way to use collection with noDataSource entities? Maybe a list or an array?

Thanks in advance for helping.

Regards,

Riccardo
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
The fake entities are still constrained by the types supported by SB, and Collection is not one of those.
thumbnail
Hemant Behera, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 36 Data de Entrada: 01/12/09 Postagens Recentes
hi David,
Is it possible to connect to multiple data sources via service builder ;i.e., more than 2,including the default one ?
Is there a good way of overriding database mapping to alter a 'double precision' column to 'numeric' in postgres, while still using service builder?

Thanks
Hemant
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
You can define all of the connections in ext-spring.xml, then each entity would include the appropriate datasource in it's definition.

You can edit the hints file to make the change to use different types/sizes within the constraints of what hibernate will support.
thumbnail
Hemant Behera, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 36 Data de Entrada: 01/12/09 Postagens Recentes
Thanks David for the quick reply.
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
in v6.1 I get a

Caused by: java.lang.ClassNotFoundException: org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy

when using in ext-spring.xml

<bean id="noDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="liferayDataSource" />
</bean>
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Be sure to include spring-jdbc.jar as a dependent jar for your project.
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
I previously posted the below in another forum post ; not sure if it is ethical to repost like this, but I thought I'd save people lookup time. As per below, I'd like to avoid including any spring jars and use built in liferay utils to create a nodatasource.



Drawing on several sources, here is an approach connecting to a second database:

ext-spring.xml

<!--?xml version="1.0"?-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
	<aop:config>
		<aop:pointcut id="transactionOperation" expression="bean(*Service.impl)" />
		<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionOperation" />
	</aop:config>
	
	<bean id="basePersistence" abstract="true">
		<property name="dataSource" ref="mydbDataSource" />
		<property name="sessionFactory" ref="mydbSessionFactory" />
	</bean>
	
	<bean id="transactionAdvice" class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil" factory-method="newBean">
		<constructor-arg value="com.liferay.portal.spring.transaction.TransactionInterceptor" />
		<constructor-arg>
			<map>
				<entry key="platformTransactionManager" value-ref="mydbTransactionManager" />
				<entry key="transactionAttributeSource" value-ref="transactionAttributeSource" />
			</map>
		</constructor-arg>
	</bean>
	

	
	<bean id="mydbHibernateSessionFactory" class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil" factory-method="newBean">
		<constructor-arg value="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration" />
		<constructor-arg>
			<map>
				<entry key="dataSource" value-ref="mydbDataSource" />
			</map>
		</constructor-arg>
	</bean>
	<bean id="mydbSessionFactory" class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil" factory-method="newBean">
		<constructor-arg value="com.liferay.portal.dao.orm.hibernate.PortletSessionFactoryImpl" />
		<constructor-arg>
			<map>
				<entry key="dataSource" value-ref="mydbDataSource" />
				<entry key="sessionFactoryClassLoader" value-ref="portletClassLoader" />
				<entry key="sessionFactoryImplementor" value-ref="mydbHibernateSessionFactory" />
			</map>
		</constructor-arg>
	</bean>
	<bean id="mydbTransactionManager" class="com.liferay.portal.kernel.util.InfrastructureUtil" factory-method="getTransactionManager" />
	
	
    <bean id="mydbDataSource" class="ca.iable.util.PropertiesBasedDataSource" factory-method="getDataSource">
    	<constructor-arg value="jdbc.mydb." />  
    </bean>	
    
</beans>


service.xml

<!--?xml version="1.0" encoding="UTF-8"?-->

<service-builder package-path="ca.iable.services">
	<author>jbakker</author>
	<namespace>services</namespace>

	<entity name="Global" table="global" data-source="mydbDataSource" local-service="true" remote-service="true" session-factory="mydbSessionFactory" tx-manager="mydbTransactionManager">

		<!-- PK fields -->

		<column name="global_id" db-name="global_id" type="int" primary="true" id-type="sequence" id-param="global_id_seq" />

		<!-- Other fields -->

		<column name="name" type="String" />
		<column name="value" type="String" />

		<finder name="Name" return-type="Global" unique="true">
			<finder-column name="name" />
		</finder>
	</entity>
	
	<entity name="Subscribe" table="subscribe" data-source="mydbDataSource" local-service="true" remote-service="true" session-factory="mydbSessionFactory" tx-manager="mydbTransactionManager">

		<!-- PK fields -->

		<column name="subscribe_id" db-name="subscribe_id" type="int" primary="true" id-type="sequence" id-param="subscribe_id_seq" />
		
		<column name="crea_ts" db-name="crea_ts" type="Date" />
		<column name="modi_ts" db-name="modi_ts" type="Date" />
		<!-- Other fields -->

		<column name="email" type="String" />
		<column name="source" type="String" />

		<finder name="Email" return-type="Subscribe" unique="true">
			<finder-column name="email" />
		</finder>
	</entity>
	
</service-builder>


PropertiesBasedDataSource.java

package ca.iable.util;

import com.liferay.portal.kernel.dao.jdbc.DataSourceFactoryUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.PropsUtil;
import javax.sql.DataSource;

public class PropertiesBasedDataSource {

	public PropertiesBasedDataSource() {
	};

	public static DataSource getDataSource(String propertyPrefix) {
		String driverClassName = PropsUtil.get(propertyPrefix
				+ "driverClassName");
		String url = PropsUtil.get(propertyPrefix + "url");
		String userName = PropsUtil.get(propertyPrefix + "username");
		String password = PropsUtil.get(propertyPrefix + "password");

		DataSource _dataSource = null;
		try {
			_dataSource = DataSourceFactoryUtil.initDataSource(driverClassName,
					url, userName, password);
		} catch (Exception e) {
			_log.error("unable to get datasource using prefix "
					+ propertyPrefix + " in portal-ext.properties");
		}
		return _dataSource;
	}

	private static Log _log = LogFactoryUtil
			.getLog(PropertiesBasedDataSource.class);

}


portal-ext.properties

jdbc.default.driverClassName=org.postgresql.Driver
jdbc.default.url=jdbc:postgresql://db.iable.ca/lportal_iable61?
useUnicode=true&amp;characterEncoding=UTF-8
jdbc.default.username=lportal_user
jdbc.default.password=mypassword

jdbc.mydb.driverClassName=org.postgresql.Driver
jdbc.mydb.url=jdbc:postgresql://db.iable.ca/mydb?
useUnicode=true&amp;characterEncoding=UTF-8
jdbc.mydb.username=lportal_user
jdbc.mydb.password=mypassword
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
I think reposting is fine, Jack.

Seems like so much extra work to get a fake db connection, where the lazy connection and a spring-jdbc jar is much lighter weight...
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
my post for 2nd database works like a charm

adding only spring-jdbc.jar throws additional spring errors in v6.1
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Eh, additional dependencies may be necessary. But I'm glad it's working either way.

The fake entity approach is a good one and any solution is one worth trying!
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
just to be clear, while I do have a 2nd database working per my repost here in this thread, I still am attempting ... for a fake data source ... to avoid direct references to Spring in ext-spring.xml ... as I follow what I see Liferay doing via the other META-INF/*.xml files
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Sorry? Didn't really follow you there, "avoid direct references to Spring in ext-spring.xml"? As a Spring config file, how can you avoid direct references?
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
I should have been more clear..

In v6.1.1, if you look at the various xml files in /src/META-INF for a service portlet, you'll see beans with classes in com.liferay.* packages like:

class="com.liferay.portal.kernel.spring.util.SpringFactoryUtil"

not with classes directly referencing org.springframework.* packages like:

class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"

my example in this thread shows how I avoid org.springframework.* references while still accessing a 2nd database
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Hmm, I've never shared that concern. For me, a LazyConnectionDataSourceProxy is an ideal class to use.

Frankly, Liferay has so many classes w/ so little (if any) documentation, I'd almost rather use a non-Liferay class where I can.

Then there's the update thing - the Spring classes never seem to go away. I've been bitten a couple of times using a Liferay class that gets deprecated or dropped or significantly changed when the next release comes out; with a Spring implementation, I don't have to worry about this issue.

At the end of the day, it's all wired together using Spring so using a Spring class or a Liferay class doesn't seem to matter so much.
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
this seems to work:

-- in ext-spring.xml ---

<bean id="noDataSource" class="my.util.NoDataSource" factory-method="getDataSource">
</bean>


-- add to service portlet src: my.util.NoDataSource.java --


package my.util;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import javax.sql.DataSource;

public class NoDataSource {
	public NoDataSource() {
	};
	public static DataSource getDataSource() {	
		return null;
	}
	private static Log _log = LogFactoryUtil
			.getLog(NoDataSource.class);
}


(note the need for suitable logging, as returning null might go wrong emoticon

-- add to service.xml something like the following fake entity --

<entity name="FakeEntity" local-service="true" remote-service="false" data-source="noDataSource">
		<column name="fakeEntityId" type="long" primary="true" id-type="increment" />
		<column name="value" type="String" />
	</entity>
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Hmm, I would have thought you'd have to have an implementation of the DataSource interface...

After a re-read, I see you're just using as a factory class to return a null DS. Looks like a great solution to me, Jack, and it also solves the problem if you were to use the lazy datasource proxy and actually called one of the database-bound methods (i.e. addXxx()) would actually get through to the datasource. Using null would end in an NPE, but that's better than a DB attempt...
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes
Looks like a great solution to me, Jack

Thanks man !

Now I have an ext-spring.xml that references no spring classes directly...
Be cool if there was a 'persistence' attribute to a service.xml entity reference that by default is true but when set to false the persistence related don't get generated.

I started with this as I have my eye on a NoDatasource-backed MyServiceImpl to be the main local service which in turn consumes local or remote RESTful services... however getting the httpclient, gson (or whatever) down there in the belly of a service is awkward... but I digress and am off topic again...
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
I'd take it even farther; allow the definition of a datasource within service.xml. Let SB generate the necessary spring definitions rather than placing within ext-spring.xml...

That on top of the persistence flag would make service.xml a 'more complete' service definition.

however getting the httpclient, gson (or whatever) down there in the belly of a service is awkward


Yep, it's a pain, especially if you don't want to mess with the spring beans which implement a service layer. Personally I don't want to mess with the generated service beans either.

I've taken to using singletons (as either the holder of an instance or as a the implementation itself) which you can then reference using the singleton pattern. Alternatively you can make your service object implement ApplicationContextAware (to be given a copy of the app context instance) and look up beans manually.

I do like the singleton approach; define your beans in ext-spring.xml that you need (the httpclient, etc.), then have your own MyServiceUtil class to return the instance that can be used in your XxxLocalServiceImpl as necessary...
thumbnail
Jack Bakker, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Master Postagens: 978 Data de Entrada: 03/01/10 Postagens Recentes

I do like the singleton approach; define your beans in ext-spring.xml that you need (the httpclient, etc.), then have your own MyServiceUtil class to return the instance that can be used in your XxxLocalServiceImpl as necessary...


Thanks for the lead, I'll give that a smack
thumbnail
Riccardo Rotondo, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Junior Member Postagens: 29 Data de Entrada: 11/06/10 Postagens Recentes
What if I want to create a table not accessible by third users. The idea is to create an entity where interface methods are private or simply not be exposed to the developers who will interact with the services. This because I want to force them to use other calls.

I tried to achieve that creating an entity with both local and remote service to false but then I have no way to access the database.

Is there any way to do that?

Thank you so much for your help.

Regards,

Riccardo
thumbnail
David H Nebinger, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
Okay, since some time in the later 6.0 releases, the XxxLocalServiceImpl classes have access to all of the other service objects as well as the persistence objects directly.

So if you really needed to hide an implementation, I would create your entity with the local service flag set to true. Then in the HiddenLocalServiceImpl class, override all of the base methods to throw an unsupported method exception or something. In your other XxxLocalServiceImpl classes that use the new entity, have them go to the persistence class directly to hit the table.
Marco Fargetta, modificado 10 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

New Member Postagens: 22 Data de Entrada: 30/01/12 Postagens Recentes
Actually, it the local and remote options are set to false the service builder still create the persistent layer to interact with the entity from the service.
So you can access the entity from other XXXLocalServiceImpl
thumbnail
David H Nebinger, modificado 8 Anos atrás.

RE: Using Service-Builder Entities without creating Database Tables

Liferay Legend Postagens: 14915 Data de Entrada: 02/09/06 Postagens Recentes
For anyone happening on this thread, I've created a blog entry to pull all of the concepts together and share some of the cool things you can do with fake entities:

https://www.liferay.com/web/26526/blog/-/blogs/fake-servicebuilder-entities