From 3b3135ed954168f9464f66e95adb4c8bb50e51a5 Mon Sep 17 00:00:00 2001 From: Jonas Hecht Date: Mon, 7 Nov 2016 09:53:56 +0100 Subject: [PATCH] First Version of working Auto Endpoint configuration based on WebServiceAutoDetection. --- .../configuration/CxfAutoConfiguration.java | 41 +++++++++- .../de/codecentric/cxf/TestApplication.java | 3 +- .../de/codecentric/cxf/TestConfiguration.java | 29 ------- .../codecentric/cxf/TestServiceEndpoint.java | 75 ++++++++++++++++++- ...tServiceIntegrationTestConfiguration.java} | 18 ++++- .../WebServiceAutoDetectorTest.java | 1 + ...WeatherServiceEndpointIntegrationTest.java | 53 +++++++++++++ 7 files changed, 181 insertions(+), 39 deletions(-) rename src/test/java/de/codecentric/cxf/{xmlvalidation/TestServiceXmlErrorConfiguration.java => TestServiceIntegrationTestConfiguration.java} (65%) create mode 100644 src/test/java/de/codecentric/cxf/endpoint/WeatherServiceEndpointIntegrationTest.java diff --git a/src/main/java/de/codecentric/cxf/configuration/CxfAutoConfiguration.java b/src/main/java/de/codecentric/cxf/configuration/CxfAutoConfiguration.java index 0eaef03..10354ba 100644 --- a/src/main/java/de/codecentric/cxf/configuration/CxfAutoConfiguration.java +++ b/src/main/java/de/codecentric/cxf/configuration/CxfAutoConfiguration.java @@ -3,9 +3,14 @@ import java.util.Map; import javax.servlet.Filter; +import javax.xml.ws.Endpoint; +import javax.xml.ws.Service; +import de.codecentric.cxf.autodetection.WebServiceAutoDetector; +import de.codecentric.cxf.common.BootStarterCxfException; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBus; +import org.apache.cxf.jaxws.EndpointImpl; import org.apache.cxf.transport.servlet.CXFServlet; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -39,6 +44,8 @@ public class CxfAutoConfiguration { @Value("${cxf.servicelist.title:CXF SpringBoot Starter - service list}") private String serviceListTitle; + + private static final String PUBLISH_URL_ENDING = "/WeatherService_1.0"; @Bean public ServletRegistrationBean cxfDispatcherServlet() { @@ -58,7 +65,32 @@ public ServletRegistrationBean cxfDispatcherServlet() { public SpringBus springBus() { return new SpringBus(); } - + + @Bean + public Object seiImplentation() throws BootStarterCxfException { + Class serviceEndpointInterface = WebServiceAutoDetector.searchServiceEndpointInterface(); + return WebServiceAutoDetector.searchAndInstantiateSeiImplementation(serviceEndpointInterface); + } + + @Bean + public Endpoint endpoint() throws BootStarterCxfException { + EndpointImpl endpoint = new EndpointImpl(springBus(), seiImplentation()); + // CXF JAX-WS implementation relies on the correct ServiceName as QName-Object with + // the name-Attribute´s text and the targetNamespace + // "http://www.codecentric.de/namespace/weatherservice/" + // Also the WSDLLocation must be set + endpoint.setServiceName(webServiceClient().getServiceName()); + endpoint.setWsdlLocation(webServiceClient().getWSDLDocumentLocation().toString()); + //TODO: Endpoint URL aus WSDL auslesen! + endpoint.publish(PUBLISH_URL_ENDING); + return endpoint; + } + + @Bean + public Service webServiceClient() throws BootStarterCxfException { + // Needed for correct ServiceName & WSDLLocation to publish contract first incl. original WSDL + return WebServiceAutoDetector.searchAndInstantiateWebServiceClient(); + } /** * @return the base-URL, where the WebServices are configured (eihter via property or default-value) @@ -66,6 +98,13 @@ public SpringBus springBus() { public String getBaseUrl() { return baseUrl; } + + /** + * @return the concrete Service URL-ending, where the WebService is configured according to your WSDL + */ + public String getServiceUrlEnding() { + return PUBLISH_URL_ENDING; + } // Register Filter for Correlating Logmessages from the same Service-Consumer @Bean diff --git a/src/test/java/de/codecentric/cxf/TestApplication.java b/src/test/java/de/codecentric/cxf/TestApplication.java index f84c91f..ebdfe95 100644 --- a/src/test/java/de/codecentric/cxf/TestApplication.java +++ b/src/test/java/de/codecentric/cxf/TestApplication.java @@ -1,6 +1,5 @@ package de.codecentric.cxf; -import de.codecentric.cxf.xmlvalidation.TestServiceXmlErrorConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Configuration; @@ -10,7 +9,7 @@ @EnableAutoConfiguration @Import({ TestConfiguration.class, - TestServiceXmlErrorConfiguration.class + TestServiceIntegrationTestConfiguration.class }) public class TestApplication { diff --git a/src/test/java/de/codecentric/cxf/TestConfiguration.java b/src/test/java/de/codecentric/cxf/TestConfiguration.java index cb41b75..21ee7b3 100644 --- a/src/test/java/de/codecentric/cxf/TestConfiguration.java +++ b/src/test/java/de/codecentric/cxf/TestConfiguration.java @@ -17,35 +17,6 @@ @Configuration public class TestConfiguration { - public static final String PUBLISH_URL_ENDING = "/WeatherService_1.0"; - - @Autowired - public SpringBus springBus; - - @Bean - public WeatherService weatherService() { - return new TestServiceEndpoint(); - } - - @Bean - public Endpoint endpoint() { - EndpointImpl endpoint = new EndpointImpl(springBus, weatherService()); - // CXF JAX-WS implementation relies on the correct ServiceName as QName-Object with - // the name-Attribute´s text and the targetNamespace - // "http://www.codecentric.de/namespace/weatherservice/" - // Also the WSDLLocation must be set - endpoint.setServiceName(weather().getServiceName()); - endpoint.setWsdlLocation(weather().getWSDLDocumentLocation().toString()); - endpoint.publish(PUBLISH_URL_ENDING); - return endpoint; - } - - @Bean - public Weather weather() { - // Needed for correct ServiceName & WSDLLocation to publish contract first incl. original WSDL - return new Weather(); - } - // Activating XML-Schema validation with custom Fault @Bean public CustomFaultBuilder weatherFaultBuilder() { diff --git a/src/test/java/de/codecentric/cxf/TestServiceEndpoint.java b/src/test/java/de/codecentric/cxf/TestServiceEndpoint.java index ebffbf9..64d973e 100644 --- a/src/test/java/de/codecentric/cxf/TestServiceEndpoint.java +++ b/src/test/java/de/codecentric/cxf/TestServiceEndpoint.java @@ -2,32 +2,99 @@ import de.codecentric.namespace.weatherservice.WeatherException; import de.codecentric.namespace.weatherservice.WeatherService; +import de.codecentric.namespace.weatherservice.datatypes.ArrayOfForecast; +import de.codecentric.namespace.weatherservice.datatypes.Forecast; +import de.codecentric.namespace.weatherservice.datatypes.POP; +import de.codecentric.namespace.weatherservice.datatypes.Temp; import de.codecentric.namespace.weatherservice.general.ForecastRequest; import de.codecentric.namespace.weatherservice.general.ForecastReturn; import de.codecentric.namespace.weatherservice.general.WeatherInformationReturn; import de.codecentric.namespace.weatherservice.general.WeatherReturn; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.time.ZonedDateTime; +import java.util.GregorianCalendar; + public class TestServiceEndpoint implements WeatherService { + 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(); + + @Override public WeatherInformationReturn getWeatherInformation(String zip) throws WeatherException { - // TODO Auto-generated method stub + System.out.println("Doing something useful :)"); return null; } @Override public ForecastReturn getCityForecastByZIP(ForecastRequest forecastRequest) throws WeatherException { - // TODO Auto-generated method stub - return null; + + ForecastReturn forecastReturn = objectFactoryGeneral.createForecastReturn(); + forecastReturn.setCity("Weimar"); + //TODO: Map more fields + forecastReturn.setState("Deutschland"); + forecastReturn.setSuccess(true); + forecastReturn.setWeatherStationCity("Weimar"); + + forecastReturn.setForecastResult(generateForecastResult(forecastReturn.getCity())); + + return forecastReturn; } @Override public WeatherReturn getCityWeatherByZIP(ForecastRequest forecastRequest) throws WeatherException { - // TODO Auto-generated method stub + System.out.println("Doing something useful :)"); return null; } + + private static ArrayOfForecast generateForecastResult(String city) { + ArrayOfForecast forecastContainer = objectFactoryDatatypes.createArrayOfForecast(); + forecastContainer.getForecast().add(generateForecast(city)); + return forecastContainer; + } + + + private static Forecast generateForecast(String city) { + Forecast forecast = objectFactoryDatatypes.createForecast(); + forecast.setDate(generateCalendarFromNow()); + forecast.setDesciption("Vorhersage für " + city); + forecast.setTemperatures(generateTemp()); + forecast.setProbabilityOfPrecipiation(generateRegenwahrscheinlichkeit()); + return forecast; + } + + + private static POP generateRegenwahrscheinlichkeit() { + POP pop = objectFactoryDatatypes.createPOP(); + pop.setDaytime("22%"); + pop.setNighttime("5000%"); + return pop; + } + + + private static Temp generateTemp() { + Temp temp = objectFactoryDatatypes.createTemp(); + temp.setDaytimeHigh("90°"); + temp.setMorningLow("0°"); + return temp; + } + + + private static XMLGregorianCalendar generateCalendarFromNow() { + GregorianCalendar gregCal = GregorianCalendar.from(ZonedDateTime.now()); + XMLGregorianCalendar xmlGregCal = null; + try { + xmlGregCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregCal); + } catch (DatatypeConfigurationException exception) { + //LOG.calenderMappingNotWorking(exception); + } + return xmlGregCal; + } } diff --git a/src/test/java/de/codecentric/cxf/xmlvalidation/TestServiceXmlErrorConfiguration.java b/src/test/java/de/codecentric/cxf/TestServiceIntegrationTestConfiguration.java similarity index 65% rename from src/test/java/de/codecentric/cxf/xmlvalidation/TestServiceXmlErrorConfiguration.java rename to src/test/java/de/codecentric/cxf/TestServiceIntegrationTestConfiguration.java index 1b86d21..9d2f158 100644 --- a/src/test/java/de/codecentric/cxf/xmlvalidation/TestServiceXmlErrorConfiguration.java +++ b/src/test/java/de/codecentric/cxf/TestServiceIntegrationTestConfiguration.java @@ -1,5 +1,6 @@ -package de.codecentric.cxf.xmlvalidation; +package de.codecentric.cxf; +import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,7 +14,18 @@ @Configuration @Import(TestConfiguration.class) -public class TestServiceXmlErrorConfiguration { +public class TestServiceIntegrationTestConfiguration { + + /* + * CXF JaxWs Client + */ + @Bean + public WeatherService weatherServiceClient() { + JaxWsProxyFactoryBean jaxWsFactory = new JaxWsProxyFactoryBean(); + jaxWsFactory.setServiceClass(WeatherService.class); + jaxWsFactory.setAddress(buildUrl()); + return (WeatherService) jaxWsFactory.create(); + } @Bean public SoapRawClient soapRawClient() throws BootStarterCxfException { @@ -23,7 +35,7 @@ public SoapRawClient soapRawClient() throws BootStarterCxfException { private String buildUrl() { // return something like http://localhost:8084/soap-api/WeatherSoapService - return "http://localhost:8087" + cxfAutoConfiguration.getBaseUrl() + TestConfiguration.PUBLISH_URL_ENDING; + return "http://localhost:8087" + cxfAutoConfiguration.getBaseUrl() + cxfAutoConfiguration.getServiceUrlEnding(); } @Autowired diff --git a/src/test/java/de/codecentric/cxf/autodetection/WebServiceAutoDetectorTest.java b/src/test/java/de/codecentric/cxf/autodetection/WebServiceAutoDetectorTest.java index 99ebf96..0d0e05d 100644 --- a/src/test/java/de/codecentric/cxf/autodetection/WebServiceAutoDetectorTest.java +++ b/src/test/java/de/codecentric/cxf/autodetection/WebServiceAutoDetectorTest.java @@ -47,4 +47,5 @@ public void isWebServiceClientSuccessfullyFoundAndInstantiated() throws BootStar QName serviceNameQName = webServiceClient.getServiceName(); assertThat(serviceNameQName.getLocalPart(), is(equalTo("Weather"))); } + } diff --git a/src/test/java/de/codecentric/cxf/endpoint/WeatherServiceEndpointIntegrationTest.java b/src/test/java/de/codecentric/cxf/endpoint/WeatherServiceEndpointIntegrationTest.java new file mode 100644 index 0000000..0c3132c --- /dev/null +++ b/src/test/java/de/codecentric/cxf/endpoint/WeatherServiceEndpointIntegrationTest.java @@ -0,0 +1,53 @@ +package de.codecentric.cxf.endpoint; + + +import de.codecentric.cxf.TestApplication; +import de.codecentric.cxf.common.BootStarterCxfException; +import de.codecentric.cxf.common.XmlUtils; +import de.codecentric.namespace.weatherservice.WeatherException; +import de.codecentric.namespace.weatherservice.WeatherService; +import de.codecentric.namespace.weatherservice.general.ForecastReturn; +import de.codecentric.namespace.weatherservice.general.GetCityForecastByZIP; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.Resource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = TestApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, + properties = { "server.port:8087" } +) +public class WeatherServiceEndpointIntegrationTest { + + @Autowired + private WeatherService weatherServiceClient; + + @Value(value="classpath:requests/GetCityForecastByZIPTest.xml") + private Resource GetCityForecastByZIPTestXml; + + @Test + public void isEndpointCorrectlyAutoDetectedAndConfigured() throws WeatherException, BootStarterCxfException, IOException { + // Given + GetCityForecastByZIP getCityForecastByZIP = XmlUtils.readSoapMessageFromStreamAndUnmarshallBody2Object( + GetCityForecastByZIPTestXml.getInputStream(), GetCityForecastByZIP.class); + + // When + ForecastReturn forecastReturn = weatherServiceClient.getCityForecastByZIP(getCityForecastByZIP.getForecastRequest()); + + // Then + assertNotNull(forecastReturn); + assertEquals("Weimar", forecastReturn.getCity()); + assertEquals("22%", forecastReturn.getForecastResult().getForecast().get(0).getProbabilityOfPrecipiation().getDaytime()); + } +}