Visualização combinada Visão plana Exibição em árvore
Tópicos [ Anterior | Próximo ]
toggle
Andy S
Service Builder - Return complex type
17 de Novembro de 2012 10:37
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Hi,

Hope you can help me. I'm using LR 6.1 EE to build a web service. The service.xml contains an empty entity tag because I want to modify the implementation class to access an external system. My web service will be accessed remotely via SOAP.

1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">
3<service-builder package-path="my.package">
4    <author>Foo</author>
5    <namespace>myspace</namespace>
6    <entity name="foo" local-service="true" remote-service="true">
7    </entity>
8</service-builder>


For example, suppose I want to return the following type:
1public class Status {
2    int    status;
3    String    statusDescription;
4}


My question is, what steps do I need to take in order to return my Status type from this web service and be able to access it as a SOAP web service. Is this possible ?

Thanks for any help you can give me with this, this is my first Liferay project and I'm a bit stuck.
Pavel Savinov
RE: Service Builder - Return complex type
18 de Novembro de 2012 10:09
Resposta

Pavel Savinov

Ranking: Junior Member

Mensagens: 97

Data de entrada: 24 de Setembro de 2012

Mensagens recentes

Hi Andy!

You should create an entity with 2 columns - status and statusDescription and a finder which returns an entity, like this:
 1<entity name="Status" local-service="true" remote-service="true" human-name="Status">
 2  <column name="statusId" type="int"/>
 3  <column name="statusDescription" type="String"/>
 4  <!-- other columns -->
 5
 6  <finder name="StatusId" return-type="Status">
 7     <finder-column name="statusDescription"/>
 8  </finder>
 9</entity>
10<!-- other entities -->

such code will generate a service(remote(which could be accessible via SOAP) and local. Then you have to implement your finder method in *ServiceImpl class and rebuild the service builder to add your finder to *ServiceUtil class.

You can read more about Service Builder in the development guide:
http://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/service-build-5
http://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/soap-web-services
Andy S
RE: Service Builder - Return complex type
18 de Novembro de 2012 14:44
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Hi Pavel,

Thanks for getting back to me so quickly!
You should create an entity with 2 columns ...

I guess this will create a table in the Liferay database. If so can I delete it after modifying the implementation class and would there be anything else to clear up?
Pavel Savinov
RE: Service Builder - Return complex type
18 de Novembro de 2012 23:29
Resposta

Pavel Savinov

Ranking: Junior Member

Mensagens: 97

Data de entrada: 24 de Setembro de 2012

Mensagens recentes

Sure, you can specify not to use the data-source in the entity's definition.
Check out last post in that thread:
http://www.liferay.com/community/forums/-/message_boards/message/16407861
Andy S
RE: Service Builder - Return complex type
19 de Novembro de 2012 09:31
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Hi Pavel,
I've tried using an entity similar to the one you showed me and I need a bit more advice if possible. Here is what I did:-
1. Used this entity and ran build-service:-
1<entity name="Status" local-service="true" remote-service="true">
2    <column name="statusId" type="int" primary="true"/>
3    <column name="statusDescription" type="String"/>
4    <finder name="StatusId" return-type="Status">
5        <finder-column name="statusId"/>
6    </finder>
7</entity>


2. Added import statement to StatusServiceImpl.java
1import *package*.service.base.StatusServiceBaseImpl;


3. The problem comes when I try to add the finder method to the StatusServiceImpl.java
1public Status findByStatusId(){
2       ...?
3    }


My question is; how do I instantiate a Status object and populate it's properties (statusId and statusDescription) before returning it?
Pavel Savinov
RE: Service Builder - Return complex type
19 de Novembro de 2012 10:21
Resposta

Pavel Savinov

Ranking: Junior Member

Mensagens: 97

Data de entrada: 24 de Setembro de 2012

Mensagens recentes

In fact, it's just your own decision, for example, you can create in directly, like this:

in your StatusServiceImpl.java:
1
2public Status findByStatusId(long statusId) {
3   Status status = new StatusImpl();
4   /* StatusImpl was generated by ServiceBuilder  */
5   status.setStatusId(statusId);
6   status.setDescription("Only one status for any ID!");
7   return status;
8}

and than re-run ServiceBuilder, or create some helper class which will generate your Status object depending on the passed statusId.
I'm not sure that it's the most elegant solution of the problem, but it'll work.
Andy S
RE: Service Builder - Return complex type
19 de Novembro de 2012 13:20
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Thanks Pavel,

I tried that and the service builds.
Andy S
RE: Service Builder - Return complex type
20 de Novembro de 2012 08:34
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Hi Pavel,

Thanks for your help so far, I really appreciate it!

I've mainly got this working now, but there is still an issue I need advice for. In order to get the service builder to build the service I had to include a primaryKey="true" attribute in the Status entity
1<entity name="Status" local-service="true" remote-service="true">
2    <column name="statusId" type="int" primary="true"/>
3    <column name="statusDescription" type="String"/>
4    <finder name="StatusId" return-type="Status">
5        <finder-column name="statusId"/>
6    </finder>
7</entity>


Here is the test method that returns some dummy values
1public Status getStatus (){
2        Status status = new StatusImpl();
3        status.setStatusDescription("status description");
4        status.setStatusId(0);
5        return status;
6    }


Here is the response from the SOAP service when called
 1<?xml version="1.0" encoding="utf-8"?>
 2<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 3    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 4    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 5    <soapenv:Body>
 6        <ns1:getStatusResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
 7            xmlns:ns1="urn:http.service.mynamespace">
 8            <getStatusReturn href="#id0"/>
 9        </ns1:getStatusResponse>
10        <multiRef id="id0" soapenc:root="0"
11            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
12            xsi:type="ns2:StatusSoap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
13            xmlns:ns2="http://model.mynamespace">
14            <primaryKey href="#id1"/>
15            <statusDescription xsi:type="soapenc:string">status description</statusDescription>
16            <statusId href="#id2"/>
17        </multiRef>
18        <multiRef id="id2" soapenc:root="0"
19            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int"
20            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</multiRef>
21        <multiRef id="id1" soapenc:root="0"
22            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int"
23            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</multiRef>
24    </soapenv:Body>
25</soapenv:Envelope>


The addition of the primary key in the entity is causing the service to generate the multiref elements and appears to substitute my dummy value for statusId into it, complicating the output.

If I try removing the primaryKey="true" attribute, then I get the following exception when running build-service
1freemarker.template.TemplateModelException: Method public boolean com.liferay.portal.tools.servicebuilder.Entity.isHierarchicalTree() threw an exception when invoked on com.liferay.portal.tools.servicebuilder.Entity@9432bc12
2...
3Caused by: java.lang.RuntimeException: There is no primary key for entity Status
4...

This is why I added the primary key attribute.

Do you any way around this?

Is there a way of getting the service to build without using the primary key route I took ?
Pavel Savinov
RE: Service Builder - Return complex type
20 de Novembro de 2012 10:03
Resposta

Pavel Savinov

Ranking: Junior Member

Mensagens: 97

Data de entrada: 24 de Setembro de 2012

Mensagens recentes

Hmm...
I've taken a look at the ServiceBuilder's source...unfortunatelly, it's necesary to create at least one column, marked as a primary key.
You can create some utility column, which will act like a PK, but use only statusId and statusDescription.
Andy S
RE: Service Builder - Return complex type
20 de Novembro de 2012 12:20
Resposta

Andy S

Ranking: New Member

Mensagens: 8

Data de entrada: 8 de Setembro de 2010

Mensagens recentes

Thanks Pavel,

I tried that and added a pk column to the Status entity and set attribute primary="true" and removed the primary attribute from the statusId element. This now returns even more multiRef elements. Here's an extract from the WSDL
 1...
 2<complexType name="StatusSoap">
 3    <sequence>
 4        <element name="pk" type="xsd:int"/>
 5        <element name="primaryKey" type="xsd:int"/>
 6        <element name="statusDescription" nillable="true" type="soapenc:string"/>
 7        <element name="statusId" type="xsd:int"/>
 8    </sequence>
 9</complexType>
10...

I think its determined to have primary key fields in the SOAP response. Perhaps this just isn't possible to achieve. Would you agree?

There is one other approach that's been suggested to me, which is to modify the Apache Axis 1.4 WSDD file by adding a beanMapping element. As described here: https://ws.apache.org/axis/java/user-guide.html#EncodingYourBeansTheBeanSerializer. From your understanding of Service Builder. Do you think its worth trying this ?