Why is the Spring Boot autoconfiguration for FhirRestfulServerConfiguration conditional on a AbstractJaxRsProvider?

351 views
Skip to first unread message

plus....@gmail.com

unread,
May 11, 2020, 5:29:07 AM5/11/20
to HAPI FHIR

Question Context


Project: hapi-fhir-spring-boot-autoconfigure (v4.2.0)
File/Class: FhirAutoConfiguration.FhirRestfulServerConfiguration

@Configuration
@ConditionalOnClass(AbstractJaxRsProvider.class)
@EnableConfigurationProperties(FhirProperties.class)
@ConfigurationProperties("hapi.fhir.rest")
@SuppressWarnings("serial")
static class FhirRestfulServerConfiguration extends RestfulServer {
    ...
}


Question


I was just wondering the reasoning behind why an autoconfiguration of a RestfulServer (Servlet based) is @ConditionalOnClass(AbstractJaxRsProvider.class) (A JAX-RS Server based class)?


If I don't include hapi-fhir-jaxrsserver-base, then my fhir server fails to start (as expected). Anyone know if this is intended behaviour?  


Thanks.

James Agnew

unread,
May 11, 2020, 10:10:29 AM5/11/20
to plus....@gmail.com, HAPI FHIR
For what it's worth, the Spring Boot support was an external contribution that sadly hasn't seen a lot of love since then. Patches (with tests) are welcome if you can see room for improvement.

Cheers,
James

--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/5da3dcb6-080a-4e3c-87e0-f868709cdf39%40googlegroups.com.

Keith Boone

unread,
May 11, 2020, 5:37:06 PM5/11/20
to James Agnew, plus....@gmail.com, HAPI FHIR

Having used it, and had to diagnose challenges, I can tell you a lot of it is about conditional structure in Spring Boot, and wanting to be able to integrate with existing JAX implementation support already present if I remember my review (over a year ago) correctly.

 

It’s good stuff, but you kind of have to be familiar with the internals of how Spring Boot works to adjust things.

 

I did manage to figure my way around this stuff, but it took a while.  To be fair, it would have taken anyone with as much knowledge as I had about Spring Boot to start with (exactly 0) to understand it.  I think others more familiar with that paradigm would be less challenged.

 

                Keith

 

Keith Boone, Enterprise Architect
kbo...@ainq.com | (617) 640-7007

AUDACIOUS INQUIRY
Bold Solutions for Connected Healthcare®
ainq.com|Twitter|YouTube|Facebook| LinkedIn

bruno....@gmail.com

unread,
May 13, 2020, 11:10:18 AM5/13/20
to HAPI FHIR
I posted a few weeks ago on a similar topic (Spring Boot/HAPI/JAXRS...)

I subsequently spent some time tinkering to create what I believe is a minimal Spring Boot/HAPI-FHIR server skeleton. The POM references as parent spring-boot-starter-parent. HAPI-FHIR artefacts are hapi-fhir-spring-boot-starter and server, base and R4. HAPI-FHIR config is done in the WebServlet extending HAPI-FHIR RestfulServer. There exists a @SpringBootTest class.

Any feedback on this would be appreciated. 

On Monday, 11 May 2020 10:10:29 UTC-4, James Agnew wrote:
For what it's worth, the Spring Boot support was an external contribution that sadly hasn't seen a lot of love since then. Patches (with tests) are welcome if you can see room for improvement.

Cheers,
James

On Mon, May 11, 2020 at 5:29 AM <plus...@gmail.com> wrote:

Question Context


Project: hapi-fhir-spring-boot-autoconfigure (v4.2.0)
File/Class: FhirAutoConfiguration.FhirRestfulServerConfiguration

@Configuration
@ConditionalOnClass(AbstractJaxRsProvider.class)
@EnableConfigurationProperties(FhirProperties.class)
@ConfigurationProperties("hapi.fhir.rest")
@SuppressWarnings("serial")
static class FhirRestfulServerConfiguration extends RestfulServer {
    ...
}


Question


I was just wondering the reasoning behind why an autoconfiguration of a RestfulServer (Servlet based) is @ConditionalOnClass(AbstractJaxRsProvider.class) (A JAX-RS Server based class)?


If I don't include hapi-fhir-jaxrsserver-base, then my fhir server fails to start (as expected). Anyone know if this is intended behaviour?  


Thanks.

--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi...@googlegroups.com.

bruno....@gmail.com

unread,
May 13, 2020, 1:38:21 PM5/13/20
to HAPI FHIR
E.g. one quirk (bug?) I wondered about ...


Configuring this in application.properties becomes mandatory in order to make this project work:

hapi.fhir.version=R4


If you do not configure it, but instead try to do it in the initialization of the servlet (where your other FHIR configuration is done):

setFhirContext(FhirContext.forR4());


you end get the following startup error:


Caused by: java.lang.IllegalStateException: Could not find the HAPI-FHIR structure JAR on the classpath for version DSTU2. Note that as of HAPI-FHIR v0.8, a separate FHIR strcture JAR must be added to your classpath (or project pom.xml if you are using Maven)
 at ca
.uhn.fhir.context.FhirContext.<init>(FhirContext.java:153)
 at ca
.uhn.fhir.context.FhirContext.<init>(FhirContext.java:145)
 at ca
.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration.fhirContext(FhirAutoConfiguration.java:88)
 at ca
.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$$EnhancerBySpringCGLIB$$cadcae0d.CGLIB$fhirContext$0(<generated>)
 at ca
.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$$EnhancerBySpringCGLIB$$cadcae0d$$FastClassBySpringCGLIB$$fccb3e64.invoke(<generated>)
 at org
.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
 at org
.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
 at ca
.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$$EnhancerBySpringCGLIB$$cadcae0d.fhirContext(<generated>)
 at sun
.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun
.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun
.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java
.lang.reflect.Method.invoke(Method.java:498)
 at org
.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
 
... 84 common frames omitted

So it appears the FhirAutoConfiguration needs this property to exist even if you're programatically trying to create a context with R4?

Detlef Böhm

unread,
Feb 8, 2022, 7:52:02 AM2/8/22
to HAPI FHIR
Hello  rbhman, hi others,

I used Your  minimal Spring Boot/HAPI-FHIR server skeleton which I found also on other places for bootstrapping my Spring-Boot Application based on the SimpleServer as a provider, interceptor, filter and router  for specific Rest-calls to our HAPI-JPA - Server behind the firewall.

I built specific providers (e.g. an OrganizationResourceProvider)  which uses @Search, @Create, @Read, @Update and @Delete-Endpoints to perform CRUD and an @Operation(type = Organization.class, name = "$tsearch", idempotent = true, manualRequest = true) for a specif search-type using POST and GET.
The  OrganizationResourceProvider is registered as you proposed to the SimpleRestfulServer. All works well from a Postman - client routing the endpoints to the HAPI-JPA-server using the internal FhirContext.forR4().newRestfulGenericClient(this.hapiServerUrl) client.

I would like to test the provider methods, but using mockMvc I can not reach this endpoints. 

When starting the Tests it is obvious, that the providers are not loaded in the context, as when starting the application.

How can I bring my TestContext up that providers are registered through SimpleRestfulServer and reachable in the TestContext.

@SpringBootTest
@AutoConfigureMockMvc
public class SearchProviderComponentTest {

@MockBean
private SearchService service;

@Autowired
private MockMvc mockMvc;

@Autowired
private FhirContext fhirContext;


@Test
public void testGetOrganizationFindByNameSuccessReturnBundleWithOrganization() throws Exception {
final Bundle organizationBundle = this.createOrganizationBundle(this.createOrganization());
when(this.service.searchByUrl("Organization?name=Good")).thenReturn(organizationBundle);
this.mockMvc.perform(get("/fhir/Organization?name=Good").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isOk());
}

I tried a lot in configuration of the TestContext, I cannot summarize all efforts, but without success. To be honest, I'm looking for a happy path example now, using mockMvc to reach the provider endpoints. 
Of course a discussion is very welome as well :-) Is using MockMvc possible at all ?  What needs to be done ? 

Thanks in advance 
Detlef
Reply all
Reply to author
Forward
0 new messages