I'm trying to create service bus using camel and cxf component. Cxf endpoint should receive any soap requests.
I have following snippet:
context.addRoutes(new RouteBuilder() {
override def configure(): Unit = {
from("cxf://http://localhost:7778?dataFormat=PAYLOAD&properties.mtom-enabled=true")
.process(new Processor {
override def process(exchange: Exchange): Unit = {
// do something here
}
})
}
})
context.start
But during requests I get following error:
org.apache.cxf.interceptor.Fault: The given SOAPAction queryINNFL does not match an operation
What can I do to make my endpoint receive all kind of soapaction headers?
You could try to implement CXF Interceptor and connect it to the interceptor inbound chain to the proper place in the endpoint. The individual phases and examples are described there. Your interceptor implementation could then imitate the required SoapAction value, to match the wsdl.
Related
I'm learning about Apache Camel routes in Spring Boot projects and I have a project that does extension from some endpoints. The endpoints are not in this project, only the extension is done here. The extension is done using #Consume from org.apache.camel in this way:
#Consume(uri = "direct:products.create.validate.interceptor")
public void executeCreate(RequestWrapper<Product> productWrapper) {
...
}
I try to understand how this direct:products.create.validate.interceptor is mapped to an endpoint from another service. Can somebody explain me how this #Consume annotation does the mapping?
Or another example is this:
#Consume(uri = "direct:listAccountsPostHook")
public void executeCreate(RequestWrapper<Account> accountWrapper) {
...
}
Where should I look to understand how they are mapped? In the controller of the other service? I can't find any example with #Consume. Thank you!
The #Consume annotation in Apache Camel is used to subscribe to a Camel endpoint and consume messages from it. The endpoint can be either a direct endpoint or any other type of endpoint such as a JMS queue or a REST endpoint, depending on your use case.
The endpoint URI, which is specified in the uri attribute of the #Consume annotation, determines where the messages are consumed from. In your example, direct:products.create.validate.interceptor and direct:listAccountsPostHook are both direct endpoints.
In Apache Camel, direct endpoints are in-memory endpoints that allow you to send messages directly to another endpoint in the same JVM. The mapping between the endpoint and the method that consumes the messages is done by Camel's routing engine.
More on Camel Direct endpoints you can read here.
To understand how the messages are being consumed, you should look at the Camel routes that are defined in your project. In a Spring Boot project, you can define your Camel routes in a RouteBuilder class. This is where you would specify the mapping between the direct endpoint and the method that will consume the messages.
For example, if you have a RouteBuilder class that looks like this:
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() {
from("direct:products.create.validate.interceptor")
.to("bean:myBean?method=executeCreate");
}
}
In this example, the direct endpoint direct:products.create.validate.interceptor is mapped to the executeCreate method in the myBean bean. The ?method=executeCreate part of the to URI tells Camel to call the executeCreate method on the myBean bean when a message is received at the endpoint.
So, in short, you should look for the Camel routes in your project that define the mapping between the endpoint and the method that consumes the messages.
I am setting up a validation framework for REST endpoint using Camel REST DSL. I came across RestConfiguration property "producerApiDoc". I have a swagger/openAPI YAML file and trying to pass it as the argument for doing the request validation but the validation doesn't happen. Below is the code for making this configuration.
Here's the Camel REST DSL documentation link!
public class EmployeeRouterConfig extends RouteBuilder {
#Override
public void configure() throws Exception {
// Rest and Swagger configuration
restConfiguration().bindingMode(RestBindingMode.json).producerApiDoc("C:\\project\\workspace\\employee-management\\schema\\Employee-system-services-api-35.yaml")
.component("servlet")
.dataFormatProperty("prettyPrint", "true")
.dataFormatProperty("json.in.enableFeatures",
"FAIL_ON_NUMBERS_FOR_ENUMS,USE_BIG_DECIMAL_FOR_FLOATS" +
",FAIL_ON_UNKNOWN_PROPERTIES,ADJUST_DATES_TO_CONTEXT_TIME_ZONE")
.dataFormatProperty("json.in.disableFeatures", "FAIL_ON_EMPTY_BEANS")
.enableCORS(true).port(env.getProperty("server.port", "8080"))
.contextPath(contextPath.substring(0, contextPath.length() -
2)).apiContextPath("/api-doc") .apiProperty("api.title","Employee Management").apiProperty("api.version", "1.0.0").clientRequestValidation(true);
I'm expecting a validation to take place based on the yaml file specified and to thrown Bad request exception, but actually the validation is not happening and the flow continues with success OK message
I need to manage different versions that come in the URL of the Webservice. I'm using a common method in the Webservice for SOAP and REST, and when I tried to get the path in the endPoint class I got the correct path for REST, but not for SOAP(I got a null in this case), does anybody how to get the path in soap?
The url looks like: http://localhost:8083/webService/v1/test and the code is:
#Stateless
#WebService(endpointInterface = "ItestgEndpoint", serviceName="testService")
#Component("testEndpoint")
#Path("/webService")
#Consumes({MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_XML})
public class TestEndpoint implements ItestgEndpoint{
#PUT
#Path("/{version}/test")
#Consumes({MediaType.APPLICATION_XML })
#Produces({MediaType.APPLICATION_XML })
#WebResult(name="testResponse")
public testResponse testEvent(#WebParam(targetNamespace="http://test/web", name="message")
#RequestParam MessageClass message,
#WebParam(name="version") #PathParam("version") String version
) throws TimeoutException, EMSException, ValidationException, AuthenticationException {
logger.info(version);
}
I saw this post SOAP and REST Webservice with one implementation in Java EE, but it didn't solve my problem.
Thanks
SOAP has no "path" like REST has. Depending on the service toolkit you use (CXF, axis, ...) you may need to collect the information in the request that you can extract from the transport mechanism of the soap message. This may or may not be available to you.
Usually, you wire the SOAP service to a path in a configuration. For example in axis, you set the soap servlet dispatcher in the web.xml, same is for cxf. The actual service is then wired in the beans.xml or services.wsdd.
The SOAP handler finds the service by the name of the endpoint and will then send the call to that endpoint which will dispatch it to the right method. The method is in the transmitted SOAP header, not in the URI.
In REST, the identification of the target service/method is in the URI, not in the XML.
So, in my opinion, for SOAP, this is by declaration and the wiring is static, while in REST, you can have the version as a path parameter.
UPDATE: Since everything is possible if you just try hard enough :-) you could rewrite the dispatcher code to allow an extra path parameter on SOAP, maybe the available packages allow some kind of interceptor class, that allows you to rewrite the SOAP header to point to another endpoint, depending on a header attribute that you invent.
I am working on spring integration for calling a soap service. I am able to call a soap service using outbound gateway successfully. Now I need to call the same soap service, with same request and now I need add some parameters in http headers.Can anybody help me out in achieving this task . Thank you very much in advance.
You can achieve with request-callback injection to the <int-ws:outbound-gateway>:
public class AddHeaderWebServiceMessageCallback implements WebServiceMessageCallback {
public void doWithMessage(WebServiceMessage message) {
CommonsHttpConnection connection = (CommonsHttpConnection) context.getConnection();
PostMethod postMethod = connection.getPostMethod();
postMethod.addRequestHeader( "foo", "bar" );
}
}
Or... If you need to do that dinamically for each requestMessage you should overcome that with the custom SoapHeaderMapper. Where you can extract CommonsHttpConnection from the TransportContextHolder.getTransportContext().getConnection()
I have written a custom interceptor that does some parameter validation. I want to be able to return an error code and serialize a JAXB-annotated class as the response body.
If I throw a WebApplicationException, it doesn't have any special processing done to serialize the Response object inside (which makes sense; I assume that is done by another interceptor).
How should I go about stopping the interceptor chain but still have JAXB serialize the response entity?
Well, at least in the CXF JAX-RS interceptor flow, if you set:
message.getExchange().put(Response.class, response);
...then the actual service does not get invoked, while the other phases do get invoked. Haven't dug in to the CXF code to see where that logic kicks in.
So I built a response like this:
Response response = Response
.status(Response.Status.FORBIDDEN)
.entity(new ErrorEntity("This is a JAXB object with an error string"))
.build();
I also have some custom authentication running in a CXF JAX-RS filter and I only want to check the parameters when the authentication is alright, so I set my parameter interceptor class to run during the PRE_INVOKE phase.