FHIR Client
FhirClientFactoryโ
FhirClientFactory.forContext(SmartLaunchContext ctx) creates a HAPI IGenericClient configured for the current session:
@Component
public class FhirClientFactory {
private final FhirContext fhirCtx = FhirContext.forR4();
private final FhirProperties props;
public IGenericClient forContext(SmartLaunchContext ctx) {
IGenericClient client = fhirCtx.newRestfulGenericClient(ctx.getFhirBaseUrl());
// Bearer token on every request
client.registerInterceptor(
new BearerTokenInterceptor(ctx.getAccessToken()));
// Timeouts
fhirCtx.getRestfulClientFactory()
.setConnectTimeout(props.getConnectTimeoutMs());
fhirCtx.getRestfulClientFactory()
.setSocketTimeout(props.getSocketTimeoutMs());
return client;
}
}
Making FHIR callsโ
Read a Patientโ
IGenericClient client = fhirClientFactory.forContext(ctx);
Patient patient = client
.read()
.resource(Patient.class)
.withId(ctx.getPatientId())
.execute();
Search for Conditionsโ
Bundle bundle = client
.search()
.forResource(Condition.class)
.where(Condition.PATIENT.hasId(ctx.getPatientId()))
.sort().descending(Condition.RECORDED_DATE)
.returnBundle(Bundle.class)
.execute();
List<Condition> conditions = bundle.getEntry().stream()
.map(e -> (Condition) e.getResource())
.toList();
Search for Medicationsโ
Bundle bundle = client
.search()
.forResource(MedicationRequest.class)
.where(MedicationRequest.PATIENT.hasId(ctx.getPatientId()))
.where(MedicationRequest.STATUS.exactly().code("active"))
.returnBundle(Bundle.class)
.execute();
Error handlingโ
HAPI throws typed exceptions. Catch ResourceNotFoundException for 404, AuthenticationException for 401 (token expired before refresh ran):
try {
Patient patient = client.read()...execute();
} catch (ResourceNotFoundException e) {
throw new PatientNotFoundException(ctx.getPatientId());
} catch (AuthenticationException e) {
// TokenRefreshFilter should have handled this;
// if we get here, force a re-launch
return "redirect:/launch?error=token_expired";
}
Timeout defaultsโ
| Property | Default | Description |
|---|---|---|
smart.fhir.connect-timeout-ms | 10000 | TCP connection timeout |
smart.fhir.socket-timeout-ms | 30000 | Socket read timeout |
Increase socket-timeout-ms if Epic FHIR searches are slow on large patient populations.
Next: OIDC & User Profile โ