I create the SOAP endpoint in my spring boot project
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
return new ServletRegistrationBean(servlet, "/project/soap/*");
}
#Bean(name="CollaborationMessageService")
public Wsdl11Definition defaultWsdl11Definition() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("/META-INF/wsdl/oracle/CollaborationMessageService.wsdl"));
return wsdl11Definition;
}
}
The endpoint is accessible in using below URL:-
http://localhost:8080/project/soap/CollaborationMessageService.wsdl
I want endpoint URL to be like:-
http://localhost:8080/project/soap/CollaborationMessageService?wsdl
is there any possible way to make these changes?
Related
I'm implementing SOAP WS services with Spring Boot.
To be able to filter requests based on the request URI, I want to provide different Endpoint implementation at different URI mappings.
To do so, I register both mapping with the servlet registration bean first:
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
...
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*", "/special/*" );
}
and then I register my Endpoint for each mapping:
#Bean(name = "serviceA")
public DefaultWsdl11Definition caseDocumentWsdl11Definition(XsdSchema caseASchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CaseAPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace(CaseAEndpoint.NAMESPACE_URI);
wsdl11Definition.setSchema(caseASchema);
return wsdl11Definition;
}
#Bean(name = "serviceB")
public DefaultWsdl11Definition caseDocumentBkkWsdl11Definition(XsdSchema caseBSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CaseBPort");
wsdl11Definition.setLocationUri("/special");
wsdl11Definition.setTargetNamespace(CaseBEndpoint.NAMESPACE_URI);
wsdl11Definition.setSchema(caseBSchema);
return wsdl11Definition;
}
Now, the undesired effect I see is that when I send a request with the payload for service A to the URI of service B, e.g. with curl:
curl --header "content-type: text/xml" -d #caseARequest.xml http://localhost:8081/special/
it is handled by CaseAEndpoint implementation even though that is not registered (with setLocationUri) to handle it.
Thus, the plan to use the request URI to filter requests nd secure the endpoints does not work.
Any hint on what I'm missing or I need to add?
(As a workaround I added check in the endpoint impl based on the request URI using ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString().contains("special")) but that's not how it should be and not what the API suggests, right?
Here's my webserviceConfig class:
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "src/main/resources/wsdl/*");
}
#Bean(name = "evaluateIMSRule")
public DefaultWsdl11Definition getRuleEngineSchema(XsdSchema ruleEngineSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("port");
wsdl11Definition.setLocationUri("src/main/resources/wsdl/evaluateIMSRule/");
wsdl11Definition.setTargetNamespace("services/mobility");
wsdl11Definition.setSchema(ruleEngineSchema);
return wsdl11Definition;
}
#Bean(name = "itemNOSService")
public DefaultWsdl11Definition getItemNOSSchema(XsdSchema itemNOSSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("port");
wsdl11Definition.setLocationUri("src/main/resources/wsdl/itemNotOnShelf/");
wsdl11Definition.setTargetNamespace("services/mobility");
wsdl11Definition.setSchema(itemNOSSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema ruleEngineSchema() {
return new SimpleXsdSchema(new ClassPathResource("src/main/resources/wsdl/evaluateIMSRule/evaluateIMSRule.xsd"));
}
#Bean
public XsdSchema itemNOSSchema() {
return new SimpleXsdSchema(new ClassPathResource("src/main/resources/wsdl/itemNotOnShelf/itemNotOnShelf.xsd"));
}
}
and here is my controller,
#EnableAsync
#Endpoint
public class ServiceController {
#PayloadRoot(namespace = "services/mobility", localPart = "evaluateIMSRule")
#ResponsePayload
public String getRuleEngineResponse(#RequestPayload EvaluateIMSRuleRequest request) {
....
....
return response;
}
#PayloadRoot(namespace = "services/mobility", localPart = "itemNOSService")
#ResponsePayload()
public CreateItemNOSRecordResponse getItemNOSServiceResponse(#RequestPayload CreateItemNOSRecordRequest request) {
....
....
return nosRecordResponse;
}
}
When I start the SpringBoot application in my local, and hit the endpoint, 'evaluaetIMSRule',
it says No endpoint mapping found for [SaajSoapMessage {http://www.xmlns/*/datatypes/evaluateIMSRule/1.0/}evaluateIMSRule]. Need help.
I'm using Spring Boot 1.3.* to build a contract first web service. I looked at the answer for the question at How to use WSDL with spring-boot? . This worked fine
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
//http://localhost:8080/ws/services.wsdl --bean name is set to 'services'
#Bean(name = "services")
public Wsdl11Definition defaultWsdl11Definition() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("/schema/MyWsdl.wsdl")); //your wsdl location
return wsdl11Definition;
}
}
My wsdl is now located at http://localhost:8080/ws/services.wsdl . Problem is that the application that will be the consumer of this web service requires the wsdl url to be written as
http://localhost:8080/ws/services?wsdl
How can i achieve this?
To configure urlrewrite as a bean check this tuckey-url-rewrite-filter-java-class-configuration
This will forward in backend and user will not be notified. Ad this rule in your urlrewrite.xml
<rule>
<from>/ws/services?wsdl</from>
<to>/ws/services.wsdl</to>
</rule>
I've created a SOAP web service using Spring Boot, based on this tuto : https://spring.io/guides/gs/producing-web-service/#scratch.
The web service works great. But I can't reach the Actuator endpoints normally embedded in Spring Boot applications : /env, /health, etc.
Here is the main configuration class of my application :
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
public final static Logger logger = Logger.getLogger( WebServiceConfig.class );
#Autowired
private WSProperties wsProperties;
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext( applicationContext );
servlet.setTransformWsdlLocations( true );
String urlMappings = wsProperties.getLocationUri() + "/*";
return new ServletRegistrationBean( servlet, urlMappings );
}
/*
* Wsdl11Definition based on a static existing WSDL file
*/
#Bean(name = "myDomain")
public Wsdl11Definition staticWsdl11Definition( XsdSchema schema ){
logger.info("Loading Wsdl11Definition from existing WSDL file");
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl( new ClassPathResource( wsProperties.getWsdlLocation() ) );
return wsdl11Definition;
}
#Bean
public XsdSchema schema() {
logger.info("Loading XSD schema");
return new SimpleXsdSchema( new ClassPathResource( wsProperties.getSchemaLocation() ) );
}
/*
* Declaration of the custom EsceptionResolver to customize SoapFault elements when some exception is thrown.
*/
#Bean(name = "soapFaultAnnotationExceptionResolver")
public DetailSoapFaultDefinitionExceptionResolver exceptionResolver( ApplicationContext applicationContext ){
DetailSoapFaultDefinitionExceptionResolver exceptionResolver = new DetailSoapFaultDefinitionExceptionResolver();
SoapFaultDefinition soapFaultDefinition = new SoapFaultDefinition();
soapFaultDefinition.setFaultCode( SoapFaultDefinition.SERVER );
exceptionResolver.setDefaultFault( soapFaultDefinition );
return exceptionResolver;
}
/*
* Message source for internationalization.
*/
#Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:locale/messages");
messageSource.setCacheSeconds(3600); // refresh cache once per hour
return messageSource;
}
}
Any idea ?
I was missing spring-boot-starter-actuator dependency in my pom.xml file.
I learn create Web Service soap from guide Producing a SOAP web service
When I have jar file and run main method everything is ok. I change to war file run by mvn spring-boot:run is the same.
But next i have a problem and I wont resolve it without use xml configuration (if I can) only annotation or java code
I found many similar issue but none was help
e.g
https://stackoverflow.com/questions/21115205/spring-boot-with-spring-ws-soap-endpoint-not-accessable
http://stackoverflow.com/questions/26873168/spring-boot-webservice-from-wsdl-not-working
Deploy war on wildFly 8.2 after that show wsdl but nothing else.
I change
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
to
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(WebServiceConfig.class);
}
}
and deploy in wildFly 8.2 after that show wsdl but when put request in SoapUI
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="http://spring.io/guides/gs-producing-web-service">
<soapenv:Header/>
<soapenv:Body>
<gs:getCountryRequest>
<gs:name>Spain</gs:name>
</gs:getCountryRequest>
</soapenv:Body>
</soapenv:Envelope>
get
WARN [org.springframework.ws.server.EndpointNotFound] (default task-7) No endpoint mapping found `for [SaajSoapMessage {http://spring.io/guides/gs-producing-web-service}getCountryRequest]`
and clear page in soapUI
I search similar issue e.g Endpoint not accessable
changed
#Bean
public ServletRegistrationBean dispatcherServlet(
ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
to
#Bean
public MessageDispatcherServlet dispatcherServlet() {
return new MessageDispatcherServlet();
}
is the same, but when I use
#Bean
public MessageDispatcherServlet dispatcherServlet() {
return new MessageDispatcherServlet(getContext());
}
private WebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new
AnnotationConfigWebApplicationContext();
context.setConfigLocation(Application.class.getName());
return context;
}
get
Caused by: java.lang.NoSuchMethodError: org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.applicationContext(Lorg/springframework/context/ApplicationContext;)Lorg/springframework/http/converter/json/Jackson2ObjectMapperBuilder;
whole error log and whole eclipse project
Thanks M. Deinum for reply it's really helpful.
First I tried use only Application class but I couldn't run server. Error in log Caused by: java.lang.ClassNotFoundException: org.xnio.SslClientAuthMode next I found solution with create two classes WebServiceConfig and Application.After changing server started , wsdl showed for me it was good change, therefore thank you again.
This issue is caused spring-boot bug GitHub, now I moving whole code from WebServiceConfig to Application and using the newest compile spring-boot. After that WS work good.In pom Paste current Application class maybe someone will have the same problem.
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Application.class);
}
#Bean
public ServletRegistrationBean dispatcherServlet(
ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
#Bean(name = "countries")
public DefaultWsdl11Definition defaultWsdl11Definition(
XsdSchema countriesSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CountriesPort");
wsdl11Definition.setLocationUri("/ws/");
wsdl11Definition
.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
wsdl11Definition.setSchema(countriesSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema countriesSchema() {
return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
}
private WebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(Application.class.getName());
return context;
}
}