Handle error from wrong path in CXF Server - java

I'm trying to handle error in CXF rest service. Which i want to gain is a situation when user is trying to send request and he's choosing a wrong path. I would like to handle this situation. The default responses are:
2014-05-15 14:07:14 INFO [qtp811959489-40] LoggingOutInterceptor:234 - Outbound Message
---------------------------
ID: 1
Response-Code: 405
Content-Type:
Headers: {Allow=[POST, GET, OPTIONS, HEAD], Date=[Thu, 15 May 2014 12:07:14 GMT], Content-Length=[0]}
My resource class:
#Path("payment/v1/")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
#Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class OneApiResource {
#GET
#Path("/{endUserId}/transactions")
public PaymentTransactionListWrapper listTransactions(#PathParam("endUserId") String endUserId) {
return null;
}
}
endpoint:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
">
<bean id="jsonProviderFactory" class="model.oneApi.JsonProviderFactory"/>
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<cxf:rsServer id="bieService"
address="http://{{endpoint.jetty.app.oneApi.host}}:{{endpoint.jetty.app.oneApi.service.port}}/{{endpoint.jetty.app.oneApi.service.ctx}}/"
loggingFeatureEnabled="true"
serviceClass="model.oneApi.OneApiResource"
loggingSizeLimit="-1"
skipFaultLogging="false">
<cxf:providers>
<bean factory-bean="jsonProviderFactory" factory-method="create"/>
</cxf:providers>
<cxf:inFaultInterceptors>
<ref bean="logOutbound"/>
</cxf:inFaultInterceptors>
<cxf:outFaultInterceptors>
<ref bean="logOutbound"/>
</cxf:outFaultInterceptors>
</cxf:rsServer>
</beans>
Is there any way to handle it?

Related

Changing Camel REST HTTP Binding Configuration

I'm using Camel REST with Camel servlet handling the REST transport and want to change the way headers from the exchange are processed in HTTP requests and responses. I'm using Spring XML to configure my application. Here's the relevant configuration I'm using:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- Custom Camel Configuration //////////////////////////////////////////////////////////////////////////////// -->
<bean id="myHttpBinding" class="com.example.MyHttpBinding"/>
<bean id="servlet" class="org.apache.camel.component.servlet.ServletComponent">
<property name="httpBinding" ref="myHttpBinding"/>
</bean>
<!-- Routes //////////////////////////////////////////////////////////////////////////////////////////////////// -->
<camel:camelContext id="myCamelContext">
<camel:contextScan/>
<camel:restConfiguration component="servlet" enableCORS="true" bindingMode="json" skipBindingOnErrorCode="false">
<camel:corsHeaders key="Access-Control-Allow-Methods" value="PATCH, PUT, POST, DELETE, GET, OPTIONS, HEAD"/>
<camel:corsHeaders key="Access-Control-Allow-Origin" value="*"/>
<camel:corsHeaders key="Access-Control-Allow-Headers" value="*"/>
</camel:restConfiguration>
</camel:camelContext>
</beans>
When the routes are created, I see that the endpoints are configured with MyHttpBinding set. However, incoming requests are still using ServletRestHttpBinding. This is because when Camel creates the consumer, it executes this block of code:
if (!map.containsKey("httpBinding")) {
// use the rest binding, if not using a custom http binding
HttpBinding binding = new ServletRestHttpBinding();
binding.setHeaderFilterStrategy(endpoint.getHeaderFilterStrategy());
binding.setTransferException(endpoint.isTransferException());
binding.setEagerCheckContentAvailable(endpoint.isEagerCheckContentAvailable());
endpoint.setHttpBinding(binding);
}
How can I set the HTTP binding in a way that Camel will respect it?
Because Camel ultimately looks for the httpBinding property on the endpoint to determine the binding strategy to use, the REST component has to be configured to add that property to the endpoint like so:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- Custom Camel Configuration //////////////////////////////////////////////////////////////////////////////// -->
<bean id="myHttpBinding" class="com.example.MyHttpBinding"/>
<!-- Routes //////////////////////////////////////////////////////////////////////////////////////////////////// -->
<camel:camelContext id="myCamelContext">
<camel:contextScan/>
<camel:restConfiguration component="servlet" enableCORS="true" bindingMode="json" skipBindingOnErrorCode="false">
<camel:endpointProperty key="httpBinding" value="myHttpBinding"/>
<camel:corsHeaders key="Access-Control-Allow-Methods" value="PATCH, PUT, POST, DELETE, GET, OPTIONS, HEAD"/>
<camel:corsHeaders key="Access-Control-Allow-Origin" value="*"/>
<camel:corsHeaders key="Access-Control-Allow-Headers" value="*"/>
</camel:restConfiguration>
</camel:camelContext>
</beans>
Note that I removed the custom servlet component because it wasn't necessary.

Json/Jackson ResponseEntity 406 Error - spring mvc 4

sorry my english.
i try to solve this error but i don´t know what could be
I'm new with spring and REST
i'm using:
*spring mvc 4.0.1
*NetBeans 8
*Hibernate
*Tomcat 8
*Oracle
*Json / Jackson REST
*AngularJS
the ERROR is 406 error when i try to get in my controller a object list with Json, when i try to get a simple String the answer is 200 (OK)
i try to add this line >> <mvc:annotation-driven/> in my dispatcher-servlet but then return:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is org.springframework.http.InvalidMediaTypeException: Invalid mime type "String": does not contain '/' <<<
so, next the code without the previous line and with 406 ERROR:
Dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="controller"/>
<context:annotation-config />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
<property name="prefixJson" value="true"/>
</bean>
PerfilesController.java
...
#ResponseStatus(value=HttpStatus.OK)
#RequestMapping(value= "perfiles.serv", method = RequestMethod.GET, headers="Accept=*/*", produces= {"application/xml", "application/json", "String"})
public #ResponseBody ResponseEntity<List<Perfiles>> getAllProfiles() {
PerfilesService pService = new PerfilesService();
List<Perfiles> list = pService.getAllProfles();
return new ResponseEntity<List<Perfiles>>(list, HttpStatus.OK);
}
...
i call with angular JS
app.service
svservicios.service('PerfilesService',['$http', function ($http) {
function getPerfiles(pageNumber,size) {
pageNumber = pageNumber > 0?pageNumber - 1:0;
return $http({
method: 'GET',
headers: {
'Content-Type': 'application/json','Accept': 'application/json, */*'
},
url: 'perfiles.serv?page='+pageNumber+'&size='+size
});
}
return {
getPerfiles: getPerfiles
};
}]);
the view:
<div class="edit-contenedor">
<div class = "btnAddPerfil">
<md-button href="crearP.html" class = "col-md-12 md-raised">Agregar Perfil</md-button>
</div>
<div>
<div ng-controller="AdminPerfilesController">
<div ui-grid="gridOptions" class="grid-ap" ui-grid-pagination>
</div>
</div>
</div>
thanks
I resolve with this in my dispatcher-servlet:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
thanks to spring mvc not returning json content - error 406

Spring 4 MVC REST (json response) - works on localhost, getting “Circular view path” on deployed host

I've created a simple Spring-based web application, with a #RestController annotation for a class that one of its mappings returns a JSON response.
It works perfectly when I run it on localhost, but I get the following error when I try to call the url on the host it is deployed to (Bluemix). I got this exception on the localhost version, when I didn't define the class as #RestController (or it's parallel - #Controller & #ResponseBody):
'Exception thrown by application class 'org.springframework.web.servlet.view.InternalResourceView.prepareForRendering:205'
javax.servlet.ServletException: Circular view path [nextStep]: would dispatch back to the current handler URL [/nextStep] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)'
These are my definitions:
RestController
#Controller
#ResponseBody
public class InterviewRESTController {
#Autowired
private transient InterviewFlowLogic interviewFlowLogic;
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/nextStep")
public ServiceRESTResponse nextStep(#RequestParam(value="name", defaultValue="World") String name){
return new ServiceRESTResponse(counter.incrementAndGet(),
String.format(template, name));
}
}
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="il.intervyo.client.controller"></context:component-scan>
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/xml" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
</bean>
</beans>
Again, it is important to stress out that this code works when I run it localhost and the url returns the Json format response, but fails only on the deployed version - I saw the few questions-and-answers that are already on the site, non of them refers to this specific issue.
I'd gladly supply with any additional info needed (pom.xml, web.xml, etc.)

CXF validation custom handler

I'm creating a webservice with cxf in the following way:
<cxf:cxfEndpoint id=XXXEndpoint"
serviceClass="com.Sth"
address="${webservices.url}/XXX"
wsdlURL="${wsdl.address}/services/XXX.wsdl"
endpointName="m:XXXPort"
serviceName="m:XXXService"
xmlns:m="http://com.sth/XXX">
<cxf:properties>
<entry key="schema-validation-enabled" value="true" />
</cxf:properties>
</cxf:cxfEndpoint>
it works perfectly, also added schema validation. I cannot add a custom validation handler. How can I do that?
I'm not sure what you mean by custom validation handler.
If you want to change validation error handling you can create class implementing javax.xml.bind.ValidationEventHandler
For instance I used this approach to prevent JAXB from throwing exception on the first encountered error. My custom event handler collected all non-fatal validation errors and thrown appropriate exception after validating whole incoming message.
Sample use of ValidationEventHandler
In order to use your custom validation event handler you should add jaxb-validation-event-handler property:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<jaxws:endpoint id="HTTPEndpoint"
implementor="org.dpytel.servicemix.cxf.wsdlfirst.PersonImpl" address="/PersonService"
wsdlLocation="wsdl/person.wsdl" endpointName="e:soap" serviceName="s:PersonService"
xmlns:e="http://servicemix.apache.org/samples/wsdl-first" xmlns:s="http://servicemix.apache.org/samples/wsdl-first">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
<entry key="jaxb-validation-event-handler">
<bean class="org.dpytel.servicemix.cxf.wsdlfirst.MyCustomHandler"></bean>
</entry>
</jaxws:properties>
</jaxws:endpoint>
</beans>
Camel CXF endpoint configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<cxf:cxfEndpoint id="personEndpoint" address="/person"
serviceClass="org.apache.servicemix.samples.wsdl_first.Person"
wsdlURL="wsdl/person.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="true" />
<entry key="jaxb-validation-event-handler">
<bean class="org.dpytel.servicemix.camel.MyCustomHandler" />
</entry>
</cxf:properties>
</cxf:cxfEndpoint>
</beans>
Example handler that disables validation error and just logs the validation message:
import java.util.logging.Logger;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
public class MyCustomHandler implements ValidationEventHandler {
private Logger logger = Logger.getLogger(this.getClass().getCanonicalName());
public boolean handleEvent(ValidationEvent event) {
logger.severe("Error: " + event.getMessage());
return true;
}
}
Please note that some validation errors will cause CXF to skip calling your handler (See details of DataReaderImpl.WSUIDValidationHandler.handleEvent(...)). Your handler will be skipped if error message contains ":Id" string, or is one of the following errors:
cvc-type.3.1.1
cvc-type.3.2.2
cvc-complex-type.3.1.1
cvc-complex-type.3.2.2
(frankly it seems like a dirty hack in CXF and if it is a problem for you I would create a bug for CXF team).
If you want more error handling customization you should probably consider writing your own Interceptor. Probably the best phase to perform such validation would be one of (PRE/USER/POST)_LOGICAL.

camel cxf request/response

i have problem with build my own webservice based on cxf/camel.
My webservice should do something like this:
I am on DomainA from which i send POST data to my webservice (CXF)
my CXF code is:
#Path("/")
#ProduceMime({ "application/json" })
public class SSO {
#POST
#Path("/user")
#ProduceMime({ "application/json" })
public String user(#FormParam("id") String token) {
}
}
My CXF code receive my id variable.
Now i want to send this variable to other url http://localhost:8080/myWebSite and wait for response from the url and after get the response send it to DomainA
my beans.xml is:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" />
<bean id="cxfSSO" class="com.esb.cxf.SSO" />
<jaxrs:server id="sso" address="/sso">
<jaxrs:serviceBeans>
<ref bean="cxfSSO" />
</jaxrs:serviceBeans>
</jaxrs:server>
</beans>
The easiest way is going to be a Spring RestTemplate, as this hides a huge amount of the complexity that you'd otherwise have to deal with.
The Spring documentation describes the basics, but be aware that you'll want to build the request as a MultiValueMap<String, String> so that it will be sent to the service as application/x-www-form-urlencoded.

Categories

Resources