Foren

JAX-RS Client in Liferay 7

thumbnail
Severin Rohner, geändert vor 7 Jahren.

JAX-RS Client in Liferay 7

Junior Member Beiträge: 43 Beitrittsdatum: 28.01.14 Neueste Beiträge
I tried to implement a simple jax-rs client. I saw that Liferay 7.0.1 GA2 has the Apache CXF included, so I tried to use it.

First I tried this JAX RS2.0 Client API Example
This didn't work, because the ClientBuilder is looking for a org.glassfish.jersey.client.JerseyClientBuilder implementation:
java.lang.RuntimeException: java.lang.ClassNotFoundException: org.glassfish.jersey.client.JerseyClientBuilder cannot be found by com.liferay.portal.remote.cxf.common_2.0.5
        at javax.ws.rs.client.ClientBuilder.newBuilder(ClientBuilder.java:103)


I tried to add the Jersey Implementation with runtime scope to the Gradle dependencies, but this didn't wook too. (I'm new to Gradle and OSGI, it seems that it works different then in Liferay 6.2 with maven.)

After this, I tried to implement the client with the CXF API: JCXF WebClient API
I add the dependency
compile group: "org.apache.cxf", name: "cxf-rt-rs-client", version: "3.0.3"
but during the deployment, this error occures in the Blade output and the module don't start:
Updated bundle 485
start 485
org.osgi.framework.BundleException: Could not resolve module: com.clavisit.test.rsclient [485]
  Unresolved requirement: Import-Package: org.apache.cxf.jaxrs.client; version="[3.0.0,4.0.0)"

I check over the gogo shell the cxf version and it is correct (3.0.3)

Can anyone help me to use the Apache CXF of Liferay 7 or to add/use the Jersey client.
thumbnail
Antonio Musarra, geändert vor 7 Jahren.

RE: JAX-RS Client in Liferay 7

Junior Member Beiträge: 66 Beitrittsdatum: 09.08.11 Neueste Beiträge
Hi Severin.
For JAX-RS you should use portal-remote-cxf-jaxrs-common instead portal-remote-cxf-common (for JAX-WS)

Bye,
Antonio.
thumbnail
Severin Rohner, geändert vor 7 Jahren.

RE: JAX-RS Client in Liferay 7

Junior Member Beiträge: 43 Beitrittsdatum: 28.01.14 Neueste Beiträge
Hi Antonio
Thanks for your answer. Where can I declare to use the portal-remote-cxf-jaxrs-common.
I tried to add it as compile dependency and remove the other jax dependencies, but without any success.

Then the JAX RS2.0 Client API Example has still the same error.
The JCXF WebClient API example don't work, because the class WebClient is not known.

Can you give me a hint? Thanks.
thumbnail
Severin Rohner, geändert vor 7 Jahren.

RE: JAX-RS Client in Liferay 7 (Antwort)

Junior Member Beiträge: 43 Beitrittsdatum: 28.01.14 Neueste Beiträge
I solved the problem. IMHO the cxf rest client isn't available in the Liferay 7 GA 2.
I added it to my module and then the ClientBuilder was found. Thanks lot @David H Nebinger for his Bolg OSGi Module Dependencies

But there were a strange class cast exception:
11:04:38,765 ERROR [http-nio-8080-exec-5][SubscribeActionCommand:99] null
java.lang.RuntimeException: java.lang.ClassCastException: org.apache.cxf.jaxrs.client.ClientProviderFactory cannot be cast to org.apache.cxf.jaxrs.client.ClientProviderFactory
        at org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean.createWebClient(JAXRSClientFactoryBean.java:233)
        at org.apache.cxf.jaxrs.client.spec.ClientImpl$WebTargetImpl.initTargetClientIfNeeded(ClientImpl.java:277)
        at org.apache.cxf.jaxrs.client.spec.ClientImpl$WebTargetImpl.request(ClientImpl.java:238)
        at org.apache.cxf.jaxrs.client.spec.ClientImpl$WebTargetImpl.request(ClientImpl.java:291)
        .......
Caused by: java.lang.ClassCastException: org.apache.cxf.jaxrs.client.ClientProviderFactory cannot be cast to org.apache.cxf.jaxrs.client.ClientProviderFactory
        at org.apache.cxf.jaxrs.client.ClientProviderFactory.initBaseFactory(ClientProviderFactory.java:76)
        at org.apache.cxf.jaxrs.client.ClientProviderFactory.createInstance(ClientProviderFactory.java:56)
        at org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean.initClient(JAXRSClientFactoryBean.java:377)
        at org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean.createWebClient(JAXRSClientFactoryBean.java:225)

I've debug it, but I didn't saw the problem / what's the difference of the two classes.

So I decide to use Apache Commons http client. This woks fine for me

Here are my impl., gradle and bnd files, perhaps it helps someone.
Apache Commons http client
build.gradle:

dependencies {
	compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
	compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.6.0"
	compile group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "2.0.0"
	compile group: "javax.portlet", name: "portlet-api", version: "2.0"
	compile group: "javax.servlet", name: "servlet-api", version: "2.5"
	compile group: "jstl", name: "jstl", version: "1.2"
	compile group: "org.osgi", name: "org.osgi.compendium", version: "5.0.0"
	compile group: 'commons-httpclient', name: 'commons-httpclient', version: '3.1', ext: 'jar'
}


bnd.bnd:

Bundle-ClassPath:\
  .,\
  lib/commons-httpclient.jar

Bundle-Name: Subsciption Portlet
Bundle-SymbolicName: com.clavisit.faberplace.subscription.web
Bundle-Version: 1.0.0
-metatype: *

-includeresource:\
lib/commons-httpclient.jar=commons-httpclient*.jar


Implementation:

// Create an instance of HttpClient.
		HttpClient client = new HttpClient();

		// Create a method instance.
		GetMethod method = new GetMethod("https://myRestService.com/");
		method.setRequestHeader("Accept", "application/json");
		// Provide custom retry handler is necessary
//			method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
//					new DefaultHttpMethodRetryHandler(3, false));

		try {
			// Execute the method.
			int statusCode = client.executeMethod(method);

			if (statusCode != HttpStatus.SC_OK) {
				System.err.println("Method failed: " + method.getStatusLine());
			}

			// Read the response body.
			byte[] responseBody = method.getResponseBody();

			// Deal with the response.
			// Use caution: ensure correct character encoding and is not binary data
			System.out.println(new String(responseBody));

		} catch (HttpException e) {
			System.err.println("Fatal protocol violation: " + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			System.err.println("Fatal transport error: " + e.getMessage());
			e.printStackTrace();
		} finally {
			// Release the connection.
			method.releaseConnection();
		}


JAX-RS client (cxf)
build.gradle:
dependencies {
	compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"
	compile group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.6.0"
	compile group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "2.0.0"
	compile group: "javax.portlet", name: "portlet-api", version: "2.0"
	compile group: "javax.servlet", name: "servlet-api", version: "2.5"
	compile group: "jstl", name: "jstl", version: "1.2"
	compile group: "org.osgi", name: "org.osgi.compendium", version: "5.0.0"
    compile group: "javax.ws.rs", name: "javax.ws.rs-api", version: "2.0.1"
	compile group: "org.apache.cxf", name: "cxf-rt-rs-client", version: "3.0.3", ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-jcache_1.0_spec', version: '1.0-alpha-1', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-jcdi_1.0_spec', version: '1.0', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-atinject_1.0_spec', version: '1.0', ext: 'jar'

	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-annotation_1.1_spec', version: '1.0', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-el_2.2_spec', version: '1.0', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-interceptor_1.1_spec', version: '1.0', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-osgi-locator', version: '1.0', ext: 'jar'
	runtime group: 'org.apache.geronimo.specs', name: 'geronimo-osgi-registry', version: '1.0', ext: 'jar'
}


bnd.bnd:
Bundle-ClassPath:\
  .,\
  lib/cxf-rt-rs-client.jar,\
  lib/geronimo-jcache_1.0_spec.jar,\
  lib/geronimo-jcdi_1.0_spec.jar,\
  lib/geronimo-atinject_1.0_spec.jar,\
    lib/geronimo-annotation_1.1_spec.jar,\
    lib/geronimo-el_2.2_spec.jar,\
    lib/geronimo-interceptor_1.1_spec.jar,\
    lib/geronimo-osgi-locator.jar,\
    lib/geronimo-osgi-registry.jar


Bundle-Name: Subsciption Portlet
Bundle-SymbolicName: com.clavisit.faberplace.subscription.web
Bundle-Version: 1.0.0
-metatype: *


Import-Package:\
	!com.sun.*,\
	\
	!javax.validation.*,\
	\
	!net.sf.cglib.proxy.*,\
	\
	!org.apache.abdera.*,\
	!org.apache.aries.*,\
	!org.apache.cxf.aegis.*,\
	!org.apache.cxf.ws.policy.*,\
	!org.apache.neethi.*,\
	!org.apache.velocity.*,\
	!org.apache.xml.resolver.*,\
	!org.apache.xmlbeans.*,\
	\
	!org.junit.*,\
	\
	!org.jvnet.fastinfoset.*,\
	!org.jvnet.staxex.*,\
	\
	!org.osgi.service.blueprint.*,\
	\
	!org.relaxng.datatype.*,\
	\
	!org.slf4j.spi.*,\
	\
	!org.springframework.*,\
	\
	!org.apache.cxf.jaxrs.client.*,\
	*

-includeresource:\
lib/cxf-rt-rs-client.jar=cxf-rt-rs-client-*.jar,\
lib/geronimo-jcache_1.0_spec.jar=geronimo-jcache_1.0_spec*.jar,\
lib/geronimo-jcdi_1.0_spec.jar=geronimo-jcdi_1.0_spec*.jar,\
lib/geronimo-atinject_1.0_spec.jar=geronimo-atinject_1.0_spec*.jar,\
lib/geronimo-annotation_1.1_spec.jar=geronimo-annotation_1.1_spec*.jar,\
lib/geronimo-el_2.2_spec.jar=geronimo-el_2.2_spec*.jar,\
lib/geronimo-interceptor_1.1_spec.jar=geronimo-interceptor_1.1_spec*.jar,\
lib/geronimo-osgi-locator.jar=geronimo-osgi-locator*.jar,\
lib/geronimo-osgi-registry.jar=geronimo-osgi-registry*.jar


Implementation:

Client client = ClientBuilder.newBuilder().newClient();
WebTarget target = client.target("https://myRestService.com/");

Invocation.Builder builder = target.request(MediaType.APPLICATION_JSON_TYPE);
Response response = builder.get();
log.info(response.readEntity(String.class));
thumbnail
Antonio Musarra, geändert vor 7 Jahren.

RE: JAX-RS Client in Liferay 7

Junior Member Beiträge: 66 Beitrittsdatum: 09.08.11 Neueste Beiträge
Hi Severin.
I'm sorry for the delay but I was busy.
it is true that Liferay does not have the client component of Apache CXF for REST services. The goal of Liferay for commons-cxf is to provide the components needed for the services.
A few weeks ago I wrote on my blog an article on how to build a SOAP client with Apache CXF in Liferay.

In this case, I would adopt the same approach. Install the bundled:
  • Apache CXF Runtime JAX-RS Frontend (3.1.6)
  • Apache CXF JAX-RS Client (3.1.6)
  • javax.annotation API (1.2.0)


On the build.gradle add the dependency:
compile group: "org.apache.cxf", name: "cxf-rt-rs-client", version: "3.1.6"


The call to the rest service using WebClient Apache CXF

	@Override
	public List<customer> getCustomers() throws CRMServiceException {
		WebClient client = WebClient.create(getCRMServiceRestEndPoint());
		client.path("/customers");
		client.type(MediaType.APPLICATION_JSON_TYPE).accept(
				MediaType.APPLICATION_JSON_TYPE);
		
		Response r = client.get();
		
		return r.readEntity(new GenericType<list<customer>&gt;(){});
	}
</list<customer></customer>


Bye,
Antonio.