Message Boards

JAX-RS Application configurations

thumbnail
ali yeganeh, modified 4 Years ago.

JAX-RS Application configurations

Regular Member Posts: 148 Join Date: 5/1/19 Recent Posts
Hi
I create JAX-RS web services using the rest  template.
How can I configure JSON-binding through a JAX-RS  javax.ws.rs.core.Application class ?  
I want to know how to make settings that automatically generate JSON for me .
thumbnail
Carlos Sierra, modified 4 Years ago.

RE: JAX-RS Application configurations

Junior Member Posts: 32 Join Date: 5/21/13 Recent Posts
Hi,
Liferay uses OSGi JAX-RS Whiteboard (https://osgi.org/specification/osgi.cmpn/7.0.0/service.jaxrs.html) to provide JAX-RS Support. Liferay ships with default JSON support with the Liferay Portal Remote JAXRS Whiteboard JAXB JSON module. In version 7.1 the support was based on Jettison. From 7.2 onward it was switched to Jackson.
In order to tell the whiteboard that your application REQUIRES JSON you can add the property
osgi.jaxrs.extension.select=(osgi.jaxrs.media.type=application/json)
to your application's
@Component
annotation, or directly by name
osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)
  It should look something like:
@Component(
    property = {
        JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE + "=/users",
        JaxrsWhiteboardConstants.JAX_RS_NAME + "=Users",
        osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)
    },
service = Application.class
)

Hope it helps.
Carlos.
thumbnail
Christoph Rabel, modified 4 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
We still add the Jackson provider to the singletons since we found no other way. Good to know that we can improve that!
public class SyncApplication extends Application {
  @Override
  public Set<Object> getSingletons() {
    Set<Object> singletons = new HashSet<>();
...
   JacksonJsonProvider provider = new JacksonJsonProvider();
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    provider.setMapper(mapper);
    singletons.add(provider);
    return singletons;
  }
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
Hi Carlos, I am using OSGI JAX-RS Whiteboard pattern just like you have setup. But i notice I get a 404 or no service available when I deploy the JAX-RS bundle. Sometimes I have to stop/start the bundle or stop the liferay instance and delete the contents in the osgi/state folder for the services to be available. Do you know what could cause this problem? Is there a stability issue ?
@Component(property = { JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE + "=/portal-api",
        JaxrsWhiteboardConstants.JAX_RS_NAME + "=Portal-Api.Rest", 
        "osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)",
        "oauth2.scopechecker.type=none",
        "auth.verifier.guest.allowed=true
}, service = Application.class)

ThanksKevin
Carlos Sierra:

Hi,
Liferay uses OSGi JAX-RS Whiteboard (https://osgi.org/specification/osgi.cmpn/7.0.0/service.jaxrs.html) to provide JAX-RS Support. Liferay ships with default JSON support with the Liferay Portal Remote JAXRS Whiteboard JAXB JSON module. In version 7.1 the support was based on Jettison. From 7.2 onward it was switched to Jackson.
In order to tell the whiteboard that your application REQUIRES JSON you can add the property
osgi.jaxrs.extension.select=(osgi.jaxrs.media.type=application/json)
to your application's
@Component
annotation, or directly by name
osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)
  It should look something like:
@Component(
&nbsp;&nbsp;&nbsp; property = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JaxrsWhiteboardConstants.JAX_RS_APPLICATION_BASE + "=/users",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JaxrsWhiteboardConstants.JAX_RS_NAME + "=Users",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)
&nbsp;&nbsp;&nbsp; },
service = Application.class
)

Hope it helps.
Carlos.
thumbnail
Carlos Sierra, modified 3 Years ago.

RE: JAX-RS Application configurations

Junior Member Posts: 32 Join Date: 5/21/13 Recent Posts
<p>Hi Kevin,</p>

<p>what version of the whiteboard are you using?</p>

<p>While it is not impossible that the whiteboard has bugs we have not detected anything that might cause this in our tests.</p>

<p>Have you checked the output of <code>jaxrs:check</code> gogo shell command? You might get that behavior if you use the same <code>JaxrsWhiteboardConstants.JAX_RS_NAME</code> for different whiteboard components. When that happens the order of registration would matter in the components that are going to be available, and that situation should be reflected in <code>jaxrs:check</code> as an error.</p>

<p>Hope this helps.</p>

<p>Carlos.</p>
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
Hi CarlosWhen I ran the gogo shell command jaxrs:check I get the following:
Extensions report:
    Extension Liferay.OAuth2.annotations.feature (1868) is waiting for an application: (|(oauth2.scope.checker.type=annotations)(oauth2                                     .scopechecker.type=annotations))

Carlos Sierra:

<p>Hi Kevin,</p>

<p>what version of the whiteboard are you using?</p>

<p>While it is not impossible that the whiteboard has bugs we have not detected anything that might cause this in our tests.</p>

<p>Have you checked the output of <code>jaxrs:check</code> gogo shell command? You might get that behavior if you use the same <code>JaxrsWhiteboardConstants.JAX_RS_NAME</code> for different whiteboard components. When that happens the order of registration would matter in the components that are going to be available, and that situation should be reflected in <code>jaxrs:check</code> as an error.</p>

<p>Hope this helps.</p>

<p>Carlos.</p>
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
Kevin Matthews:

Hi CarlosWhen I ran the gogo shell command jaxrs:check I get the following:
Extensions report:
    Extension Liferay.OAuth2.annotations.feature (1868) is waiting for an application: (|(oauth2.scope.checker.type=annotations)(oauth2                                     .scopechecker.type=annotations))
I then replace oauth2.scopechecker.type=none to  oauth2.scopechecker.type=annotations. Did another jaxrs:check and did not see the Extension report. Could this resolve my problem as see the service started after I upload the bundle changes?

Carlos Sierra:

<p>Hi Kevin,</p>

<p>what version of the whiteboard are you using?</p>

<p>While it is not impossible that the whiteboard has bugs we have not detected anything that might cause this in our tests.</p>

<p>Have you checked the output of <code>jaxrs:check</code> gogo shell command? You might get that behavior if you use the same <code>JaxrsWhiteboardConstants.JAX_RS_NAME</code> for different whiteboard components. When that happens the order of registration would matter in the components that are going to be available, and that situation should be reflected in <code>jaxrs:check</code> as an error.</p>

<p>Hope this helps.</p>

<p>Carlos.</p>
thumbnail
Carlos Sierra, modified 3 Years ago.

RE: JAX-RS Application configurations

Junior Member Posts: 32 Join Date: 5/21/13 Recent Posts
Hi Kevin,
that message you were seeing in the output of jaxrs:check command is kind of expected. If your application is not using OAuth2 @RequiresScope annotation you don't need to change the oauth2.scope.checker.type.
At any rate this should not cause the behavior you were seeing nor change when you restart or clean the state folder, so I would bet something else is happening and I would probably think of a clashing of names or base url, as I mentioned in the previous post.
Hope this helps.
Carlos.
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
<p>Hi Carlos,</p>

<p>I dont have any otherJaxrsWhiteboardConstants.JAX_RS_NAME + &quot;=Portal-Api.Rest&quot; names clashing.&nbsp; The only place&nbsp;I repeat&nbsp;that name is in the Portal OAuth Control Panel under OAUth Configuration of the COntrol Panel. Which I believe we need to have it there when building web services.</p>

<p>Could the way how I created my Project workspace be an issue? Under my modules Folder I have a project that include the rest service, -service, -api components? I know this is a wild guess but in my Liferay 7.0 project I had separate project for each component and was under one folder.</p>

<p>&nbsp;</p>

<p>Thanks,</p>

<p>Kevin</p>
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
Could you try to remove that line and retest?
"osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)",
Maybe add a simple get method to it like in the rest example to test it.
When you restart it, is the module always correctly started? (I am just trying to cover all the bases). Could you check in the gogo shell?
Do you use other services? I mean, using @Reference or something? I once had an issue where I wrote
@Reference SomeService someservice;
BUT I forgot to add the service=... property to the Component annotation of SomeService and it had no interface.
@Component
public class SomeService {...}
I got no errors, it deployed fine, did not complain, but the rest services didn't appear. Took me a while to find the cause for the issue.
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
Hi Chris,
  • I remove the line "osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)", and use simple get method which i use to test to see if my service is available and it works but the problem is I am using jaxb for marshalling so I get a 415 error for my other service method .
  • When I do the jaxrs-check i get Extensions report:
        Extension jaxb-json (1330) is waiting for an application: (osgi.jaxrs.extension.select=\(osgi.jaxrs.name=jaxb-json\)) 
  • I do use other services @Reference for injection (DI) for the following: UserLocalService, GroupLocalService and custom Service builder service to access the DB MySQL. However, the way how my Gradle Project Workspace is setup  in my module folder  I have a project AMService that has all the components the -rest, -api and -service under that one folder inside the modules folder seen attached . I have other components outside that folder that doesn't seem to have an issue with starting up but I do see an issue when calling the -service module to fetch data from the DB the newly updated records are not fetched in which I have to delete the state folder and restart the instance. Would the project workspace folder structure cause an issue? 
  • I dont include the service in my @Component annotation. Wouldn't OSGI inject the service automatically when it sees the @Reference?
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
Hi,
ok, so it seems, the extension select for jaxb-json is the culprit or at least related to the issue. I am not sure if the rest of the issues has anything to do with it, I didn't want to confuse you.
The answer to the last question is: It should and I can't explain the effect I had. Maybe some kind of bug? It just happened to me.
Another thing you could test:
Create a plain rest service and add the "osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)" line (maybe add one method that needs jaxb). Does it work?
Also: Which Liferay version do you use?
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
Hi Chris, I am using liferay version 7.2.
I created a plain rest service using the Liferay IDE and added the add the "osgi.jaxrs.extension.select=(osgi.jaxrs.name=jaxb-json)" line and one method that needed jaxb and it worked fine and started instantaneously. I then added the rest of my methods from my previous project to my new project and work instantaneously on both my local pc and our development server. So, I am wondering could it be that I had my Rest Project bundle with my Service builder project under one project in the module folder. If that the case, then that's really weird and should be documented that jax-services project does not starts up properly under one project that includes the service builder. However, I may need to run further test to prove my point as this is an intermittent issue and not all the time consistently getting no services available but most time its no services available.
Thanks
Kevin
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
That could indeed be the problem. I always avoid it to add "unrelated stuff" to the service builder. It does a lot of tricky things under the hood and it could have weird sideeffects. I usually add the necessary impl methods for DB access and do all the rest in other modules.
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
<p>Hi Chris, yes I agree there a some tricky things under the hood. But I am having issue with my service builder and I am wondering if it&rsquo;s related with my Jax-rs project in the same module folder as my service and api components. I I have a dB table that gets populated by the service builder. However, when I update one of the columns from 1 to 0 . I have a service api that checks that column as a Boolean whether it&rsquo;s true or false i.e 0 or 1. The weird thing is when I manually update that column to zero I have to manually stop the device,&nbsp;&nbsp;delete the osgi and restart the service in order for one one of my service clases to see the updated value. This is really weird behave as I have never seen this before in service builder in liferay 6.2,7.0 and earlier 7.2 but now this 7.2 version is all of a sudden behaving strangely. It seems it&rsquo;s caching the last state or keeping 1 in cache. Have you experience anything with device builder not reading an updated table and need to restart the service?</p>
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
What do you mean with "manually update that column"?
Liferay caches heavily. If you circumvent the service builder methods in any way, the cache isn't invalidated and you won't see an updated value.
The cache is also in an extra module. The service module generates a cache key based on the query and stores it in the cache service. The next time the same query is executed, it tries to find the data in the cache. So, restarting the service doesn't help.
The solution to the issue depends a bit on your usecase. You have the option to manually clear the cache in Server Administration. It clears all caches, but for some usecases that could be ok. I think, there is also some method to clear the cache for a particular service/model type. But I am not sure here.
Secondly, you can disable the cache. There is a setting somewhere in Service Builder for that. But it obviously is bad for the performance.
The best solution is to use the Liferay API to update the column in the database. That way, Liferay is aware that you updated something an clears the caches accordingly.
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
When I said manually, I meant I ran a sql update in MySQL to update the column. I don’t alter service builder just use as-is out of the box when I generate my service methods.  I have a method that fetches data from the table and then updates the table if  has a metadata data value  from document library. This is very strange for the service builder classes should be able to fetch the data. Doesn’t caching expire after a period of time? 
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
I will seek a liferay api to update the column for a number of records..
Kevin Matthews, modified 3 Years ago.

RE: JAX-RS Application configurations

Expert Posts: 253 Join Date: 1/25/16 Recent Posts
hi Chris, I went in Administration screen and did database clean cache. This use case will be a one time process.
Thanks for your recommendations. emoticon
Christoph Rabel:

What do you mean with "manually update that column"?
Liferay caches heavily. If you circumvent the service builder methods in any way, the cache isn't invalidated and you won't see an updated value.
The cache is also in an extra module. The service module generates a cache key based on the query and stores it in the cache service. The next time the same query is executed, it tries to find the data in the cache. So, restarting the service doesn't help.
The solution to the issue depends a bit on your usecase. You have the option to manually clear the cache in Server Administration. It clears all caches, but for some usecases that could be ok. I think, there is also some method to clear the cache for a particular service/model type. But I am not sure here.
Secondly, you can disable the cache. There is a setting somewhere in Service Builder for that. But it obviously is bad for the performance.
The best solution is to use the Liferay API to update the column in the database. That way, Liferay is aware that you updated something an clears the caches accordingly.
thumbnail
Carlos Sierra, modified 4 Years ago.

RE: JAX-RS Application configurations

Junior Member Posts: 32 Join Date: 5/21/13 Recent Posts
hey Christoph,
if memory helps, Jackson JAX-RS provider searchs for ObjectMapper implementations using JAX-RS context resolvers. Which allows you to configure mappers even per class that you are going to serialize.
You can register ContextResolvers<ObjectMapper> just like you register any other extension so you don't have to configure it statically in the application. This is not a feature developed or supported by Liferay since it is taking for granted that the extension is backed by Jackson, which might not be the case in the future. If that is a concern to you then you can still be providing it explicitly.
Carlos.
thumbnail
Christoph Rabel, modified 4 Years ago.

RE: JAX-RS Application configurations

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
Na, not a concern.
I remember, when we started with rest services more than 2 years ago there wasn't a lot of documentation available and we had to do quite some research to find a working solution. It works for 7.0 and we won't touch the code for existing systems, but when we upgrade modules we already remove the cxf configuration and change it to Whiteboard. So, this will be just another improvement.