Do not resolve view in RESTful Application - rest

I am building a web application with RESTful web services using Spring MVC 3. The web services will be used by applications, so should never really resolve any requests to a view. Is there any way to specify in the servlet context that no requests should resolve to any view?
At the moment, I have:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
which I know tries to resolve any request to a correspondingly named view in the jsp folder. However, if I remove this, the application just tries to use a default view resolver.
The reason I am concerned about this is that my application logs are going to be full of the following messages (even though it works fine):
SEVERE: Servlet.service() for servlet [DispatcherServlet] in context with path [/vouchd] threw exception [Circular view path [signup]: would dispatch back to the current handler URL [/vouchd/signup] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)] with root cause
javax.servlet.ServletException: Circular view path [signup]: would dispatch back to the current handler URL [/vouchd/signup] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
or with the InternalViewResolver:
WARN [http-bio-8080-exec-4] (DispatcherServlet.java:1057) - No mapping found for HTTP request with URI [/app/WEB-INF/jsp/call.jsp] in DispatcherServlet with name 'DispatcherServlet'
which I guess is the better of the two evils. I don't want to turn off logging WARN level.

Try with #ResponseStatus. This code returns 204 with no content and view resolving skipped:
#ResponseStatus(NO_CONTENT)
void noView() {
//...
}
If you want to return raw data and simply serialize it to JSON or XML, use #ResponseBody:
#ResponseBody
MyPojo noView() {
return new MyPojo();
}

Related

How to set couchbase operation timeout in spring data couchbase?

I have a simple spring project which try to retrieve a document from couchbase using spring-data-couchbase. I have configured the config by extending AbstractCouchbaseConfiguration. Everything works perfectly fine.
Since I use couchbase as a cache, now I need to set the operation timeout to a lower value. Anybody can shed some light on how to do it?
According to the docs, the correct answer is wrong. That's not the way it should be done...
When you extend from AbstractCouchbaseConfiguration
Default settings can be customized through the DefaultCouchbaseEnvironment.Builder or through the setting of system properties. Latter ones take always precedence and can be used to override builder settings at runtime too. http://docs.couchbase.com/sdk-api/couchbase-java-client-2.0.0/com/couchbase/client/java/env/DefaultCouchbaseEnvironment.html
For instance, to customize the timeout connection:
#Override
protected CouchbaseEnvironment getEnvironment() {
DefaultCouchbaseEnvironment.builder().connectTimeout(15000);
return super.getEnvironment();
}
There are other options that can be assigned this way.
According the docs (https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html ),
Here is the application.properties :
spring.couchbase.env.timeouts.connect=5000ms # Bucket connections timeouts.
spring.couchbase.env.timeouts.key-value=2500ms # Blocking operations performed on a specific key timeout.
spring.couchbase.env.timeouts.query=7500ms # N1QL query operations timeout.
spring.couchbase.env.timeouts.socket-connect=1000ms # Socket connect connections timeout.
spring.couchbase.env.timeouts.view=7500ms # Regular and geospatial view operations timeout.
To define a timeout for the CouchbaseClient you have to provide it using the ConnectionFactory. Sadly, the current version of spring-data-couchbase doesn't provide a simple way to do that.
The class responsible to create connection factories is ConnectionFactoryBean, and it has a setter for the operations timeout, but I couldn't find anything for #Configuration classes.
Since you are extending AbstractCouchbaseConfiguration, you might want to override couchbaseClient():
public class MyCouchbaseConfiguration extends AbstractCouchbaseConfiguration {
...
private final CouchbaseConnectionFactoryBuilder builder = new CouchbaseConnectionFactoryBuilder();
private CouchbaseConnectionFactory connectionFactory;
...
#Override
#Bean(destroyMethod = "shutdown")
public CouchbaseClient couchbaseClient() throws Exception {
setLoggerProperty(couchbaseLogger());
if(connectionFactory == null){
builder.setOpTimeout(myTimeout);
// Set another parameters.
...
connectionFactory = builder.buildCouchbaseConnection(
bootstrapUris(bootstrapHosts()),
getBucketName(),
getBucketPassword()
);
}
return new CouchbaseClient(connectionFactory);
}
}
Also, you can call directly CouchbaseFactoryBean but it's not a good practice if you are not configuring your application using XML bean definitions.
Here is the XML configuration just in case:
<bean id="couchbase" class="org.springframework.data.couchbase.core.CouchbaseFactoryBean">
<property name="opTimeout" value="1000"/> <!-- 1 sec -->
<property name="bucket" value="myBucket"/>
<property name="password" value="myPassword"/>
<property name="host" value="myHost"/>
</bean>
<couchbase:template id="couchbaseTemplate"/>
For Spring Data Couchbase 2, adding the following property in application.properties did it
spring.couchbase.env.timeouts.connect=20000
I used queryTimeout to set the value of operation timeout as shown below:
CouchbaseEnvironment env = DefaultCouchbaseEnvironment.builder()
.connectTimeout(50000).socketConnectTimeout(50000)
.queryTimeout(1000)
.build();
this will ensure you get the response within 1s.
use this link to get different available options:
https://docs.couchbase.com/java-sdk/2.7/client-settings.html#timeout-options

Send message to a client when an HTTP method not supported

I've created a REST controller the can handle, as usual, GET, POST, PUT and DELETE HTTP requests using Spring MVC. The web server is Tomcat 8.
If a send request, for instance, with HEAD method, the response is an error page from Tomcat with message
HTTP Status 501 - Method LINK is not is not implemented by this servlet for this URI
I have such exception handler:
#ResponseBody
#ExceptionHandler(Throwable.class)
public ResponseEntity<?> exceptionHandler() {
Error error = createError("error_message.unforeseen_error");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
But it doesn't catch any error in this case.
Is there a way to send back a message wrapped in JSON object as a response instead of this Tomcat page?
The problem is that SpringMVC does not find any method for HEAD in your controller, so it does not use it and your #ExceptionHandler is not used. It would be used for exception arising inside the controller. Extract from Spring Frameword Reference : You use the #ExceptionHandler method annotation within a controller to specify which method is invoked when an exception of a specific type is thrown during the execution of controller methods (emphasis mine).
To process exception outside of any controller, you must register a HandlerExceptionResolver bean that will replace the DefaultHandlerExceptionResolver provided by default by Spring MVC. You could either directly put the Json String in the response and return null from resolve method (my prefered way), or put the elements in a model and use a view to format the Json.

Saving WS payload into database in Camel

I'm absolutely newbie in Apache Camel. I'd like to create a very simple app in which it would accept WS calls and save the payload into a database using JPA.
The payload's structure is quite simple. The root is a Marriage object. It contain some String and int and Date fields, a wife, a husband and a list of children (Person objects).
My goal is to save these data into two tables of a database: MARRIAGE, PERSON.
I've successfully created a jaxws:endpoint in which I listen and respond a dummy response.
I've created the tables and JPA entities.
I don't know how to "connect" the WS implementation with the spring configured JpaTemplate. Should I solve this problem with Camel routing using somehow a #Converter class or #Injet it into the WS implementing class by Spring. I'm confused.
Should I use cxf endpoint instead of jaxws endpoint?
You need to use camle-cxf endpoint if you want to use camel. What I would do is expose the endpoint as a camle-cxf endpoint. Something like this:
<camel-cxf:cxfEndpoint id="listenerEndpoint"
address="http://0.0.0.0:8022/Dummy/services/Dummy"
wsdlURL="wsdl/DummyService.wsdl"
xmlns:tns="http://dummy.com/ws/Dummy"
serviceName="tns:Dummy"
endpointName="tns:DummyService">
<camel-cxf:properties>
<entry key="schema-validation-enabled" value="true"/>
<entry key="dataFormat" value="PAYLOAD"/>
</camel-cxf:properties>
</camel-cxf:cxfEndpoint>
Then I would have a simple Spring bean like this:
<bean id="processor" class="com.dummy.DummyProcessor">
<property name="..." value="..."/> //there goes your data source of jdbc template or whatever...
</bean>
If you want to use JPA just configure all the configuration and inject your entity manager into this bean.
The actual class would look something like this:
public class DummyProcessor {
#Trancational //If you need transaction to be at this level...
public void processRequest(Exchange exchange) {
YourPayloadObject object = exchange.getIn().getBody(YourPayloadObject.class);
//object - is your object from SOAP request, now you can get all the data and store it in the database.
}
}
The camel route would be like this:
<camel:camelContext trace="true" id="camelContext" >
<camel:route id="listenerEndpointRoute">
<camel:from uri="cxf:bean:listenerEndpoint?dataFormat=POJO&synchronous=true" />
<camel:log message="Got message. The expected operation is :: ${headers.operationName}"/>
<camel:choice>
<camel:when>
<camel:simple>${headers.operationName} == 'YourPayloadObject'</camel:simple>
<camel:bean ref="processor" method="processRequest"/>
</camel:when>
</camel:choice>
<camel:log message="Got message before sending to target: ${headers.operationName}"/>
<camel:to uri="cxf:bean:someTargetEndpointOrSomethingElse"/>
<camel:log message="Got message received from target ${headers.operationName}"/>
</camel:route>
</camel:camelContext>
Hope this helps.

How to invoke a method in restful web service using camel-cxf?

I want to invoke a rest service using apache camel. Currently i am using the cxfrs component to configure my endpoint. My route looks like below:
from("cxfrs://http://127.0.0.1:8080/RestServiceApp/?resourceClasses="com.sample.Server.HelloWorld").log("Route Started");
My problem is that i want to invoke a method present in the server class (HelloWorld in my case). Can you please tell me how do i call a particular method?
Camel doesn't call resource class methods. From the documentation on the Camel web-site http://camel.apache.org/cxfrs.html:
This class is used to configure the JAXRS properties ONLY. The methods
will NOT be executed during the routing of messages to the endpoint,
the route itself is responsible for ALL processing instead.
You need to write a custom processing logic, for example as following:
<from uri="cxfrs://http://127.0.0.1:8080/RestServiceApp/?resourceClasses="com.sample.Server.HelloWorld">
<choice>
<when>
<simple>${header.operationName} == 'operation1'</simple>
<to uri="direct:operation1" />
</when>
<when>
<simple>${header.operationName} == 'operation2'</simple>
<to uri="direct:operation2" />
</when>
....
</choice>

Spring 3 Controller and Relative Paths

Trying to get to grips with Spring MVC Controllers. But having a problem with relative paths
I have a page at:
http://localhost:8080/jeeniweb/articles
on that page there is a menu option :
<li>Structure and Dependencies</li>`
This, in a browser, resolves to:
http://localhost:8080/jeeniweb/articles/writing_great_code/structure_and_dependencies/
When a user clicks on this link I intercept this request with a controller:
#RequestMapping(value = "/articles/{article}/{chapter}")
public String articles(#PathVariable String article, #PathVariable String chapter)
{
System.out.println("Articles Page Request");
System.out.println("article: " + article);
System.out.println("chapter: " + chapter);
return "articles/index";
}
This method catches the request and the println methdods print out the right stuff.
However after the call I want to:
http://localhost:8080/jeeniweb/articles
But in fact the browser goes to:
http://localhost:8080/mysite/articles/writing_great_code/structure_and_dependencies/
How can this be when I am returning articles/index from the method?
My Servlet config is:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
As I understand Spring this means the resultant return after the processing above code should be /WEB-INF/views/articles/index.jsp which is what I want. That's where the index.jsp page is.
Any help is much appreciated.
Thanks
Adam
The controller just knows that it intercepted the correct url, in order to resolve articles/index url, you'd need to have it return a redirect to that url such as:
return "redirect:articles/index"