Vista combinada Visión Plana Vista de árbol
Discusiones [ Anterior | Siguiente ]
toggle
Aritz Galdos
Correct way to expose model-service via JSON
8 de noviembre de 2011 4:01
Respuesta

Aritz Galdos

Ranking: Expert

Mensajes: 385

Fecha de incorporación: 15 de mayo de 2007

Mensajes recientes

Hi guys:

I am trying to expose a custom model created with service builder via JSON. So I created the model with local-service remote-service attributes set to true.
Then implemented one simple getById method in XXXLocalServiceImpl and called "ant build-service" again to regenerate classes.

When I deployed the war, every thing was OK but when trying to access the getById method via web, the portalClassLoader was not able find the apropiate class. That looks correct, as far as the *-service.jar is in portlet context and not in portal context.

Well, then I copied moved the XXX-service.jar to portals lib/ext folder to make it be loaded with the portal classLoader.

Well, now the method is invoked, and data is retrieved from DB. We are near!

The method is invoked in method getJSON of class JSONServiceAction

1Object returnObj = method.invoke(classObj, args);


At this point, returnObj is an instance of XXXClp.

After that

1if (returnObj != null) {
2                    return getReturnValue(returnObj, method.getReturnType());
3                }


is called.

getReturnValue first of all gets the serializer class name

1protected String getSerializerClassName(Object obj) {
2        String serlializerClassName = StringUtil.replace(
3            obj.getClass().getName(),
4            new String[] {".model.impl.", "Impl"},
5            new String[] {".service.http.", "JSONSerializer"});
6
7        return serlializerClassName;
8    }


but this is prepared for implementations of models, not the service classes.
For example, supose we have for instance

my.company.artifact.model.XXXClp.java

If the getSerializerClassName method is aplied, it will return the class itself.

But if we have the class wich implements the model,

my.company.artifact.model.impl.XXXImpl.java

the getSerializerClassName method will return

my.company.artifact.impl.XXXImplJSONSerializer.java

Finally, JSONServiceAction will invoke the method toJSONObject of the resultant class, which fails because my.company.artifact.model.XXXClp.java does not have such method as my.company.artifact.impl.XXXImplJSONSerializer.java does

What am I doing wrong?

Can anyone spot some light on it?


Regards!!!
Gerald Rubin
RE: Correct way to expose model-service via JSON
21 de enero de 2012 11:06
Respuesta

Gerald Rubin

Ranking: Junior Member

Mensajes: 59

Fecha de incorporación: 23 de octubre de 2011

Mensajes recientes

If you still need help with this, I can share what I've learned. I'm about 97% competent in JSON-related Liferay at this point. I've subscribed, so just tell me if you want me to write up what I do.
Roberto Paolillo
RE: Correct way to expose model-service via JSON
2 de febrero de 2012 11:10
Respuesta

Roberto Paolillo

Ranking: New Member

Mensajes: 1

Fecha de incorporación: 3 de noviembre de 2011

Mensajes recientes

I was stuck on your same point (XXX-service.jar put under lib/ext but classnotfoundexception on XXXImplJSONSerializer)

Than i realized than generating WSDD through service builder i am able to access service via JSON using:
1/XXX-portlet/json


This isn't a definitive solution for me, beacause when i try to deploy the portlet lot of exceptions like this:
1java.lang.ClassCastException: org.apache.axis.encoding.ser.BeanSerializerFactory cannot be cast to org.apache.axis.encoding.SerializerFactory


My solution to this is to put JSON filter and servlet definitions in portlet web.xml:
 1
 2    <filter>
 3        <filter-name>JSON Servlet Filter</filter-name>
 4        <filter-class>com.liferay.portal.kernel.servlet.PortalClassLoaderFilter</filter-class>
 5        <init-param>
 6            <param-name>filter-class</param-name>
 7            <param-value>com.liferay.portal.servlet.filters.secure.SecureFilter</param-value>
 8        </init-param>
 9        <init-param>
10            <param-name>portal_property_prefix</param-name>
11            <param-value>json.servlet.</param-value>
12        </init-param>
13    </filter>
14    <filter>
15        <filter-name>Secure JSON Servlet Filter</filter-name>
16        <filter-class>com.liferay.portal.kernel.servlet.PortalClassLoaderFilter</filter-class>
17        <init-param>
18            <param-name>filter-class</param-name>
19            <param-value>com.liferay.portal.servlet.filters.secure.SecureFilter</param-value>
20        </init-param>
21        <init-param>
22            <param-name>basic_auth</param-name>
23            <param-value>true</param-value>
24        </init-param>
25        <init-param>
26            <param-name>portal_property_prefix</param-name>
27            <param-value>json.servlet.</param-value>
28        </init-param>
29    </filter>
30    <filter-mapping>
31        <filter-name>JSON Servlet Filter</filter-name>
32        <url-pattern>/json/*</url-pattern>
33    </filter-mapping>
34    <filter-mapping>
35        <filter-name>Secure JSON Servlet Filter</filter-name>
36        <url-pattern>/secure/json/*</url-pattern>
37    </filter-mapping>
38    <servlet>
39        <servlet-name>JSON Servlet</servlet-name>
40        <servlet-class>com.liferay.portal.kernel.servlet.PortalClassLoaderServlet</servlet-class>
41        <init-param>
42            <param-name>servlet-class</param-name>
43            <param-value>com.liferay.portal.servlet.JSONServlet</param-value>
44        </init-param>
45        <init-param>
46            <param-name>use-portlet-class-loader</param-name>
47            <param-value>true</param-value>
48        </init-param>
49        <load-on-startup>2</load-on-startup>
50    </servlet>
51    <servlet-mapping>
52        <servlet-name>JSON Servlet</servlet-name>
53        <url-pattern>/json/*</url-pattern>
54    </servlet-mapping>
55    <servlet-mapping>
56        <servlet-name>JSON Servlet</servlet-name>
57        <url-pattern>/secure/json/*</url-pattern>
58    </servlet-mapping>   


I'm not going to use axis webservices, but any ideas about avoiding BeanSerializerFactory ClassCastException would be appreciated