Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
Prakash Khanchandani
Using Service-Builder Entities without creating Database Tables
January 13, 2012 3:04 AM
Answer

Prakash Khanchandani

Rank: Regular Member

Posts: 217

Join Date: February 10, 2011

Recent Posts

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.
Prakash Khanchandani
RE: Using Service-Builder Entities without creating Database Tables
January 16, 2012 2:24 AM
Answer

Prakash Khanchandani

Rank: Regular Member

Posts: 217

Join Date: February 10, 2011

Recent Posts

Will this be possible?

Any suggestions or any hints in this direction?

Thank you
Gerald Rubin
RE: Using Service-Builder Entities without creating Database Tables
January 16, 2012 4:48 AM
Answer

Gerald Rubin

Rank: Junior Member

Posts: 59

Join Date: October 23, 2011

Recent Posts

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
1    #
2    # Specify where to get the overridden properties. Updates should not be made
3    # on this file but on the overridden version of this file.
4    #
5    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:
1    build.number=1


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

You should be good.
Prakash Khanchandani
RE: Using Service-Builder Entities without creating Database Tables
January 16, 2012 8:58 PM
Answer

Prakash Khanchandani

Rank: Regular Member

Posts: 217

Join Date: February 10, 2011

Recent Posts

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.
Gerald Rubin
RE: Using Service-Builder Entities without creating Database Tables
January 17, 2012 2:45 AM
Answer

Gerald Rubin

Rank: Junior Member

Posts: 59

Join Date: October 23, 2011

Recent Posts

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!
Remis Baima
RE: Using Service-Builder Entities without creating Database Tables
September 14, 2012 5:17 AM
Answer

Remis Baima

Rank: New Member

Posts: 7

Join Date: November 5, 2010

Recent Posts

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>
David H Nebinger
RE: Using Service-Builder Entities without creating Database Tables
November 28, 2012 7:02 PM
Answer

David H Nebinger

Rank: Liferay Legend

Posts: 4496

Join Date: September 1, 2006

Recent Posts

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.
Riccardo Rotondo
RE: Using Service-Builder Entities without creating Database Tables
May 14, 2013 10:33 AM
Answer

Riccardo Rotondo

Rank: New Member

Posts: 17

Join Date: June 11, 2010

Recent Posts

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.

 1
 2<entity name="File"  local-service="true" remote-service="false">
 3        <column name="fileId" type="long" primary="true" id-type="increment"/>
 4        <column name="name" type="String" />
 5        <column name="userId" type="long" />
 6        <column name="size" type="long" />
 7        <column name="date" type="Date" /> 
 8        <column name="virtualPaths" type="Collection" entity="VirtualPath"
 9                mapping-table="Files_VirtualPaths" /> 
10        <column name="storageURLs" type="Collection" entity="StorageURLs"
11                mapping-key="fileId" /> 
12        <column name="tags" type="Collection" entity="Tag"
13                mapping-table="Files_Tags" />
14        <order by="asc">
15            <order-column name="name" />
16        </order>
17    </entity>
18
19<entity name="VirtualPath"  local-service="true" remote-service="false">
20        <column name="vpId" type="long" primary="true" id-type="increment"/>
21        <column name="vp" type="String" />
22        <column name="userId" type="long" />
23        <column name="date" type="Date" /> 
24        <column name="files" type="Collection" entity="File"
25                mapping-table="Files_VirtualPaths" />
26        <order by="asc">
27            <order-column name="userId" />
28            <order-column name="vp" />
29        </order>   
30        <finder name="VP_userId" return-type="VirtualPath">
31            <finder-column name="vp" />
32            <finder-column name="userId" />
33        </finder>
34    </entity>
35
36<entity name="DirectoryElement" local-service="true" remote-service="false"
37            data-source="noDataSource">
38        <column name="id" type="long" primary="true"/>
39        <column name="VirutalPathElement" type="Collection" entity="VirtualPath"
40                mapping-key="vpId"/>
41    <column name="FileElement" type="Collection" entity="File"
42                mapping-table="VirtualPath_DirectoryElement_noDataSource"/>
43    </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
David H Nebinger
RE: Using Service-Builder Entities without creating Database Tables
May 14, 2013 10:39 AM
Answer

David H Nebinger

Rank: Liferay Legend

Posts: 4496

Join Date: September 1, 2006

Recent Posts

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:

1<bean id="noDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
2  <property name="targetDataSource" ref="liferayDataSource" />
3</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.
Riccardo Rotondo
RE: Using Service-Builder Entities without creating Database Tables
May 15, 2013 9:44 AM
Answer

Riccardo Rotondo

Rank: New Member

Posts: 17

Join Date: June 11, 2010

Recent Posts

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:

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


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

 1
 2Method 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
 3The problematic instruction:
 4----------
 5==> list serviceBuilder.getMappingEntities(column.mappingTable) as mapColumn [on line 260, column 41 in com/liferay/portal/tools/servicebuilder/dependencies/model_impl.ftl]
 6----------
 7
 8Java backtrace for programmers:
 9----------
10freemarker.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
11    at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:130)
12    at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
13    at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
14    at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94)
15    at freemarker.core.Environment.visit(Environment.java:221)
16    at freemarker.core.MixedContent.accept(MixedContent.java:92)
17    at freemarker.core.Environment.visit(Environment.java:221)
18    at freemarker.core.Environment.visit(Environment.java:310)
19    at freemarker.core.CompressedBlock.accept(CompressedBlock.java:73)
20    at freemarker.core.Environment.visit(Environment.java:221)
21    at freemarker.core.MixedContent.accept(MixedContent.java:92)
22    at freemarker.core.Environment.visit(Environment.java:221)
23    at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
24    at freemarker.core.Environment.visit(Environment.java:221)
25    at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:179)
26    at freemarker.core.Environment.visit(Environment.java:428)
27    at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
28    at freemarker.core.Environment.visit(Environment.java:221)
29    at freemarker.core.MixedContent.accept(MixedContent.java:92)
30    at freemarker.core.Environment.visit(Environment.java:221)
31    at freemarker.core.Environment.process(Environment.java:199)
32    at freemarker.template.Template.process(Template.java:237)
33    at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:47)
34    at com.liferay.portal.freemarker.FreeMarkerUtil.process(FreeMarkerUtil.java:37)
35    at com.liferay.portal.tools.servicebuilder.ServiceBuilder._processTemplate(ServiceBuilder.java:4983)
36    at com.liferay.portal.tools.servicebuilder.ServiceBuilder._createModelImpl(ServiceBuilder.java:2293)
37    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.<init>(ServiceBuilder.java:671)
38    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.main(ServiceBuilder.java:151)
39Caused by: java.lang.NullPointerException
40    at com.liferay.portal.tools.servicebuilder.ServiceBuilder.getMappingEntities(ServiceBuilder.java:1048)
41    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
42    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
43    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
44    at java.lang.reflect.Method.invoke(Method.java:597)
45    at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:866)
46    at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:106)
47    ... 27 more


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

Thanks in advance for helping.

Regards,

Riccardo
David H Nebinger
RE: Using Service-Builder Entities without creating Database Tables
May 15, 2013 9:45 AM
Answer

David H Nebinger

Rank: Liferay Legend

Posts: 4496

Join Date: September 1, 2006

Recent Posts

The fake entities are still constrained by the types supported by SB, and Collection is not one of those.