Skip to content

Commit

Permalink
Added support for constructor autowiring for endpoints (fixes #56)
Browse files Browse the repository at this point in the history
  • Loading branch information
bjansen authored and bjansen-caps committed Sep 30, 2020
1 parent 46c8d91 commit 1cf3af8
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package de.codecentric.cxf.autodetection;

import de.codecentric.cxf.common.BootStarterCxfException;
import de.codecentric.cxf.autodetection.diagnostics.SeiImplClassNotFoundException;
import de.codecentric.cxf.autodetection.diagnostics.SeiNotFoundException;
import de.codecentric.cxf.autodetection.diagnostics.WebServiceClientNotFoundException;
import de.codecentric.cxf.common.BootStarterCxfException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.jws.WebService;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceClient;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


@Component
Expand All @@ -21,15 +21,17 @@ public class WebServiceAutoDetector {
private static final Logger LOG = LoggerFactory.getLogger(WebServiceAutoDetector.class);
protected static final String NO_CLASS_FOUND = "No class found";
private final WebServiceScanner webServiceScanner;
private final ApplicationContext applicationContext;

public static final Class<WebService> SEI_ANNOTATION = WebService.class;
public static final Class<WebServiceClient> WEB_SERVICE_CLIENT_ANNOTATION = WebServiceClient.class;

private final String seiAndWebServiceClientPackageName;
private final String seiImplementationPackageName;

public WebServiceAutoDetector(WebServiceScanner webServiceScanner) throws BootStarterCxfException {
public WebServiceAutoDetector(WebServiceScanner webServiceScanner, ApplicationContext applicationContext) throws BootStarterCxfException {
this.webServiceScanner = webServiceScanner;
this.applicationContext = applicationContext;
seiAndWebServiceClientPackageName = PackageNameReader.build().readSeiAndWebServiceClientPackageNameFromCxfSpringBootMavenProperties();
seiImplementationPackageName = PackageNameReader.build().readSeiImplementationPackageNameFromCxfSpringBootMavenProperties();
}
Expand Down Expand Up @@ -80,13 +82,8 @@ public Service searchAndInstantiateWebServiceClient() throws BootStarterCxfExcep

private <T> T instantiateFromClass(Class<T> clazz) throws BootStarterCxfException {
try {
Constructor<T> constructor = clazz.getConstructor();
return constructor.newInstance();

} catch (NoSuchMethodException |
IllegalAccessException |
InstantiationException |
InvocationTargetException exception) {
return applicationContext.getAutowireCapableBeanFactory().createBean(clazz);
} catch (BeansException exception) {
throw new BootStarterCxfException("Class couldn´t be instantiated", exception);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
Expand Down Expand Up @@ -58,13 +59,13 @@ public class CxfAutoConfiguration {


@Bean
public WebServiceAutoDetector webServiceAutoDetector() throws BootStarterCxfException {
return new WebServiceAutoDetector(new WebServiceScanner());
public WebServiceAutoDetector webServiceAutoDetector(ApplicationContext applicationContext) throws BootStarterCxfException {
return new WebServiceAutoDetector(new WebServiceScanner(), applicationContext);
}

@PostConstruct
public void setUp() throws BootStarterCxfException {
webServiceClient = webServiceAutoDetector().searchAndInstantiateWebServiceClient();
webServiceClient = webServiceAutoDetector(null).searchAndInstantiateWebServiceClient();
serviceUrlEnding = "/" + webServiceClient().getServiceName().getLocalPart();
}

Expand Down Expand Up @@ -106,7 +107,7 @@ public SpringBus springBus() {
@ConditionalOnProperty(name = "endpoint.autoinit", matchIfMissing = true)
public Object seiImplementation() throws BootStarterCxfException {
if(seiImplementation == null) {
seiImplementation = webServiceAutoDetector().searchAndInstantiateSeiImplementation();
seiImplementation = webServiceAutoDetector(null).searchAndInstantiateSeiImplementation();
}
return seiImplementation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import de.codecentric.namespace.weatherservice.general.WeatherReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
Expand All @@ -24,8 +26,17 @@ public class TestServiceEndpoint implements WeatherService {
private static final Logger LOG = LoggerFactory.getLogger(TestServiceEndpoint.class);
private static de.codecentric.namespace.weatherservice.general.ObjectFactory objectFactoryGeneral = new de.codecentric.namespace.weatherservice.general.ObjectFactory();
private static de.codecentric.namespace.weatherservice.datatypes.ObjectFactory objectFactoryDatatypes = new de.codecentric.namespace.weatherservice.datatypes.ObjectFactory();
private final Object injectedBean;

@Autowired
public TestServiceEndpoint(ApplicationContext context) {
this.injectedBean = context;
}

public Object getInjectedBean() {
return injectedBean;
}


@Override
public WeatherInformationReturn getWeatherInformation(String zip)
throws WeatherException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
Expand Down Expand Up @@ -51,7 +53,8 @@ public class WebServiceAutoDetectorTest {

WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassWithAnnotationAndIsAnInterface(SEI_ANNOTATION, seiAndWebServiceClientPackageName)).thenReturn(WEATHER_SERVICE_ENDPOINT_INTERFACE);
WebServiceAutoDetector webServiceAutoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
WebServiceAutoDetector webServiceAutoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

Class serviceEndpointInterface = webServiceAutoDetector.searchServiceEndpointInterface();

Expand All @@ -64,7 +67,11 @@ public class WebServiceAutoDetectorTest {

WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassWhichImplementsAndPickFirst(WEATHER_SERVICE_ENDPOINT_INTERFACE, seiImplementationPackageName)).thenReturn(WEATHER_SEI_IMPLEMENTING_CLASS);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
AutowireCapableBeanFactory beanFactory = mock(AutowireCapableBeanFactory.class);
when(applicationContext.getAutowireCapableBeanFactory()).thenReturn(beanFactory);
when(beanFactory.createBean(TestServiceEndpoint.class)).thenReturn(new TestServiceEndpoint(null));
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

WeatherService weatherServiceEndpointImpl = autoDetector.searchAndInstantiateSeiImplementation(WEATHER_SERVICE_ENDPOINT_INTERFACE);

Expand All @@ -77,7 +84,11 @@ public class WebServiceAutoDetectorTest {

WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassWithAnnotationAndPickTheFirstOneFound(WEB_SERVICE_CLIENT_ANNOTATION, seiAndWebServiceClientPackageName)).thenReturn(WEATHER_WEBSERVICE_CLIENT);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
AutowireCapableBeanFactory beanFactory = mock(AutowireCapableBeanFactory.class);
when(applicationContext.getAutowireCapableBeanFactory()).thenReturn(beanFactory);
when(beanFactory.createBean(Weather.class)).thenReturn(new Weather());
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

Service webServiceClient = autoDetector.searchAndInstantiateWebServiceClient();

Expand All @@ -92,7 +103,8 @@ public class WebServiceAutoDetectorTest {

WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassWhichImplementsAndPickFirst(WEATHER_SERVICE_ENDPOINT_INTERFACE, seiImplementationPackageName)).thenThrow(STARTER_EXCEPTION_NO_CLASS_FOUND);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

autoDetector.searchAndInstantiateSeiImplementation(WEATHER_SERVICE_ENDPOINT_INTERFACE);
}
Expand All @@ -102,7 +114,8 @@ public class WebServiceAutoDetectorTest {

WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassWithAnnotationAndPickTheFirstOneFound(WEB_SERVICE_CLIENT_ANNOTATION, seiAndWebServiceClientPackageName)).thenThrow(STARTER_EXCEPTION_NO_CLASS_FOUND);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

autoDetector.searchAndInstantiateWebServiceClient();
}
Expand All @@ -113,7 +126,8 @@ public class WebServiceAutoDetectorTest {
WebServiceScanner scannerMock = mock(WebServiceScanner.class);
when(scannerMock.scanForClassNamesWithAnnotation(SEI_ANNOTATION, seiAndWebServiceClientPackageName)).thenThrow(STARTER_EXCEPTION_NO_CLASS_FOUND);
when(scannerMock.scanForClassWithAnnotationAndIsAnInterface(SEI_ANNOTATION, seiAndWebServiceClientPackageName)).thenCallRealMethod();
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock);
ApplicationContext applicationContext = mock(ApplicationContext.class);
WebServiceAutoDetector autoDetector = new WebServiceAutoDetector(scannerMock, applicationContext);

autoDetector.searchServiceEndpointInterface();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import de.codecentric.cxf.TestApplication;
import de.codecentric.cxf.TestServiceEndpoint;
import de.codecentric.cxf.common.BootStarterCxfException;
import de.codecentric.cxf.common.XmlUtils;
import de.codecentric.namespace.weatherservice.WeatherException;
Expand Down Expand Up @@ -33,6 +34,9 @@ public class WeatherServiceEndpointSystemTest {
@Autowired
private WeatherService weatherServiceClient;

@Autowired
private TestServiceEndpoint testServiceEndpoint;

@Value(value="classpath:requests/GetCityForecastByZIPTest.xml")
private Resource GetCityForecastByZIPTestXml;

Expand All @@ -50,4 +54,9 @@ public void isEndpointCorrectlyAutoDetectedAndConfigured() throws WeatherExcepti
assertEquals("Weimar", forecastReturn.getCity());
assertEquals("22%", forecastReturn.getForecastResult().getForecast().get(0).getProbabilityOfPrecipiation().getDaytime());
}

@Test
public void isEndpointCorrectlyAutowired() {
assertNotNull(testServiceEndpoint.getInjectedBean());
}
}

0 comments on commit 1cf3af8

Please sign in to comment.