001/* 002 * #%L 003 * HAPI FHIR JAX-RS Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jaxrs.client; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.rest.api.RequestTypeEnum; 025import ca.uhn.fhir.rest.client.api.Header; 026import ca.uhn.fhir.rest.client.api.IHttpClient; 027import ca.uhn.fhir.rest.client.impl.RestfulClientFactory; 028import jakarta.ws.rs.client.Client; 029import jakarta.ws.rs.client.ClientBuilder; 030 031import java.util.List; 032import java.util.Map; 033 034/** 035 * A Restful Client Factory, based on Jax Rs 036 * Default Jax-Rs client is NOT thread safe in static context, you should create a new factory every time or 037 * use a specific Jax-Rs client implementation which managed connection pool. 038 * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare 039 */ 040public class JaxRsRestfulClientFactory extends RestfulClientFactory { 041 042 private Client myNativeClient; 043 private List<Class<?>> registeredComponents; 044 045 /** 046 * Constructor. Note that you must set the {@link FhirContext} manually using {@link #setFhirContext(FhirContext)} if this constructor is used! 047 */ 048 public JaxRsRestfulClientFactory() { 049 super(); 050 } 051 052 /** 053 * Constructor 054 * 055 * @param theFhirContext 056 * The context 057 */ 058 public JaxRsRestfulClientFactory(FhirContext theFhirContext) { 059 super(theFhirContext); 060 } 061 062 public synchronized Client getNativeClientClient() { 063 if (myNativeClient == null) { 064 ClientBuilder builder = ClientBuilder.newBuilder(); 065 myNativeClient = builder.build(); 066 } 067 068 if (registeredComponents != null && !registeredComponents.isEmpty()) { 069 for (Class<?> c : registeredComponents) { 070 myNativeClient = myNativeClient.register(c); 071 } 072 } 073 074 return myNativeClient; 075 } 076 077 @Override 078 public synchronized IHttpClient getHttpClient( 079 StringBuilder url, 080 Map<String, List<String>> theIfNoneExistParams, 081 String theIfNoneExistString, 082 RequestTypeEnum theRequestType, 083 List<Header> theHeaders) { 084 Client client = getNativeClientClient(); 085 return new JaxRsHttpClient(client, url, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders); 086 } 087 088 /*** 089 * Not supported with default Jax-Rs client implementation 090 * @param theHost 091 * The host (or null to disable proxying, as is the default) 092 * @param thePort 093 */ 094 @Override 095 public void setProxy(String theHost, Integer thePort) { 096 throw new UnsupportedOperationException(Msg.code(605) + "Proxies are not supported yet in JAX-RS client"); 097 } 098 099 /** 100 * Only accept clients of type jakarta.ws.rs.client.Client 101 * Can be used to set a specific Client implementation 102 * @param theHttpClient 103 */ 104 @Override 105 public synchronized void setHttpClient(Object theHttpClient) { 106 this.myNativeClient = (Client) theHttpClient; 107 } 108 109 /** 110 * Register a list of Jax-Rs component (provider, filter...) 111 * @param components list of Jax-Rs components to register 112 */ 113 public void register(List<Class<?>> components) { 114 registeredComponents = components; 115 } 116 117 @Override 118 protected synchronized JaxRsHttpClient getHttpClient(String theServerBase) { 119 return new JaxRsHttpClient(getNativeClientClient(), new StringBuilder(theServerBase), null, null, null, null); 120 } 121 122 @Override 123 protected void resetHttpClient() { 124 if (myNativeClient != null) myNativeClient.close(); // close client to avoid memory leak 125 myNativeClient = null; 126 } 127}