org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cxf-bundle-minimal Show documentation
Show all versions of cxf-bundle-minimal Show documentation
Apache CXF Minimal Bundle Jar
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cxf.jaxrs.client;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.ProxyHelper;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.ConduitSelector;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.endpoint.UpfrontConduitSelector;
import org.apache.cxf.feature.AbstractFeature;
import org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean;
import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
import org.apache.cxf.jaxrs.JAXRSServiceImpl;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.factory.FactoryBeanListener;
public class JAXRSClientFactoryBean extends AbstractJAXRSFactoryBean {
private static final Logger LOG = LogUtils.getL7dLogger(JAXRSClientFactoryBean.class);
private String username;
private String password;
private boolean inheritHeaders;
private MultivaluedMap headers;
private ClientState initialState;
private boolean threadSafe;
private long timeToKeepState;
private Class> serviceClass;
private ClassLoader proxyLoader;
public JAXRSClientFactoryBean() {
this(new JAXRSServiceFactoryBean());
}
public JAXRSClientFactoryBean(JAXRSServiceFactoryBean serviceFactory) {
super(serviceFactory);
serviceFactory.setEnableStaticResolution(true);
}
/**
* Sets the custom class loader to be used
* for creating proxies
* @param loader
*/
public void setClassLoader(ClassLoader loader) {
proxyLoader = loader;
}
/**
* Indicates if a single proxy or WebClient instance can be reused
* by multiple threads.
*
* @param threadSafe if true then multiple threads can invoke on
* the same proxy or WebClient instance.
*/
public void setThreadSafe(boolean threadSafe) {
this.threadSafe = threadSafe;
}
/**
* Sets the time a thread-local client state will be kept.
* This property is ignored for thread-unsafe clients
* @param secondsToKeepState
*/
public void setSecondsToKeepState(long time) {
this.timeToKeepState = time;
}
/**
* Gets the user name
* @return the name
*/
public String getUsername() {
return username;
}
/**
* Sets the username.
* Setting the username and password is a simple way to
* create a Basic Authentication token.
*
* @param username the user name
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Gets the password
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Sets the password.
* Setting the username and password is a simple way to
* create a Basic Authentication token.
*
* @param password the password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Indicates if the headers set by a current proxy will be inherited
* when a subresource proxy is created
* vice versa.
*
* @param ih if set to true then the current headers will be inherited
*/
public void setInheritHeaders(boolean ih) {
inheritHeaders = ih;
}
/**
* Sets the resource class
* @param cls the resource class
*/
public void setResourceClass(Class> cls) {
setServiceClass(cls);
}
/**
* Sets the resource class, may be called from a Spring handler
* @param cls the resource class
*/
public void setServiceClass(Class> cls) {
this.serviceClass = cls;
serviceFactory.setResourceClass(cls);
}
/**
* Returns the service class
* @param cls the service class
*/
public Class> getServiceClass() {
return serviceClass;
}
/**
* Sets the headers new proxy or WebClient instances will be
* initialized with.
*
* @param map the headers
*/
public void setHeaders(Map map) {
headers = new MetadataMap();
for (Map.Entry entry : map.entrySet()) {
String[] values = entry.getValue().split(",");
for (String v : values) {
if (v.length() != 0) {
headers.add(entry.getKey(), v);
}
}
}
}
/**
* Gets the initial headers
* @return the headers
*/
public Map> getHeaders() {
return headers;
}
/**
* Creates a WebClient instance
* @return WebClient instance
*/
public WebClient createWebClient() {
Service service = new JAXRSServiceImpl(getAddress(), getServiceName());
getServiceFactory().setService(service);
try {
Endpoint ep = createEndpoint();
ClientState actualState = getActualState();
WebClient client = actualState == null ? new WebClient(getAddress())
: new WebClient(actualState);
initClient(client, ep, actualState == null);
this.getServiceFactory().sendEvent(FactoryBeanListener.Event.CLIENT_CREATED, client, ep);
return client;
} catch (Exception ex) {
LOG.severe(ex.getClass().getName() + " : " + ex.getLocalizedMessage());
throw new RuntimeException(ex);
}
}
private ClientState getActualState() {
if (threadSafe) {
initialState = new ThreadLocalClientState(getAddress(), timeToKeepState);
}
if (initialState != null) {
return headers != null
? initialState.newState(URI.create(getAddress()), headers, null) : initialState;
} else {
return null;
}
}
/**
* Creates a proxy
* @param cls the proxy class
* @param varValues optional list of values which will be used to substitute
* template variables specified in the class-level JAX-RS Path annotations
* @return the proxy
*/
public T create(Class cls, Object... varValues) {
return cls.cast(createWithValues(varValues));
}
/**
* Create a Client instance. Proxies and WebClients are Clients.
* @return the client
*/
public Client create() {
if (serviceClass == WebClient.class) {
return createWebClient();
} else {
return createWithValues();
}
}
/**
* Create a Client instance. Proxies and WebClients are Clients.
* @param varValues optional list of values which will be used to substitute
* template variables specified in the class-level JAX-RS Path annotations
*
* @return the client
*/
public Client createWithValues(Object... varValues) {
serviceFactory.setBus(getBus());
checkResources(false);
ClassResourceInfo cri = null;
try {
Endpoint ep = createEndpoint();
if (getServiceClass() != null) {
for (ClassResourceInfo info : serviceFactory.getClassResourceInfo()) {
if (info.getServiceClass().isAssignableFrom(getServiceClass())
|| getServiceClass().isAssignableFrom(info.getServiceClass())) {
cri = info;
break;
}
}
if (cri == null) {
// can not happen in the reality
throw new RuntimeException("Service class " + getServiceClass().getName()
+ " is not recognized");
}
} else {
cri = serviceFactory.getClassResourceInfo().get(0);
}
boolean isRoot = cri.getURITemplate() != null;
ClientProxyImpl proxyImpl = null;
ClientState actualState = getActualState();
if (actualState == null) {
proxyImpl =
new ClientProxyImpl(URI.create(getAddress()), proxyLoader, cri, isRoot,
inheritHeaders, varValues);
} else {
proxyImpl =
new ClientProxyImpl(actualState, proxyLoader, cri, isRoot,
inheritHeaders, varValues);
}
initClient(proxyImpl, ep, actualState == null);
Client actualClient = null;
try {
ClassLoader theLoader = proxyLoader == null ? cri.getServiceClass().getClassLoader()
: proxyLoader;
actualClient = (Client)ProxyHelper.getProxy(theLoader,
new Class[]{cri.getServiceClass(),
Client.class,
InvocationHandlerAware.class},
proxyImpl);
} catch (Exception ex) {
actualClient = (Client)ProxyHelper.getProxy(Thread.currentThread().getContextClassLoader(),
new Class[]{cri.getServiceClass(),
Client.class,
InvocationHandlerAware.class},
proxyImpl);
}
this.getServiceFactory().sendEvent(FactoryBeanListener.Event.CLIENT_CREATED, actualClient, ep);
return actualClient;
} catch (IllegalArgumentException ex) {
String message = ex.getLocalizedMessage();
if (cri != null) {
String expected = cri.getServiceClass().getSimpleName();
if ((expected + " is not an interface").equals(message)) {
message += "; make sure CGLIB is on the classpath";
}
}
LOG.severe(ex.getClass().getName() + " : " + message);
throw ex;
} catch (Exception ex) {
LOG.severe(ex.getClass().getName() + " : " + ex.getLocalizedMessage());
throw new RuntimeException(ex);
}
}
protected ConduitSelector getConduitSelector(Endpoint ep) {
ConduitSelector cs = getConduitSelector();
if (cs == null) {
cs = new UpfrontConduitSelector();
}
cs.setEndpoint(ep);
return cs;
}
protected void initClient(AbstractClient client, Endpoint ep, boolean addHeaders) {
if (username != null) {
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setUserName(username);
authPolicy.setPassword(password);
ep.getEndpointInfo().addExtensor(authPolicy);
}
client.getConfiguration().setConduitSelector(getConduitSelector(ep));
client.getConfiguration().setBus(getBus());
client.getConfiguration().getOutInterceptors().addAll(getOutInterceptors());
client.getConfiguration().getOutInterceptors().addAll(ep.getOutInterceptors());
client.getConfiguration().getInInterceptors().addAll(getInInterceptors());
client.getConfiguration().getInInterceptors().addAll(ep.getInInterceptors());
applyFeatures(client);
if (headers != null && addHeaders) {
client.headers(headers);
}
setupFactory(ep);
}
protected void applyFeatures(AbstractClient client) {
if (getFeatures() != null) {
for (AbstractFeature feature : getFeatures()) {
feature.initialize(client.getConfiguration(), getBus());
}
}
}
/**
* Sets the initial client state, can be a thread-safe state.
* @param initialState the state
*/
public void setInitialState(ClientState initialState) {
this.initialState = initialState;
}
}