Spring WebFlow: POST from flow to MVC Controller - spring-mvc

I have MVC Controller as below and mapped /home to that controller. To redirect to /home from flow i use externalRedirect:contextRelative:/home in view attribute. Is possible to pass some data to /home in POST ?
MVC Controller
#Controller
public class MainController {
#RequestMapping(value="/home", method=RequestMethod.POST)
public String index(#RequestParam String data) {
return "index";
}
}
Flow
<end-state id="home" view="externalRedirect:contextRelative:/home" />

No.
When you are specifying externalRedirect: Spring Webflow is going to set a redirect code and Location header on your response which simply instructs the browser to perform a GET request for the specified location. You can include query parameters appended to this location but not POST data.
For example:
<end-state id="home" view="externalRedirect:contextRelative:/home?foo=bar" />
Also note that you can include ${expressions} in this string that will be evaluated against the request context, according to the XSD.

Related

How to use "RestController" and "Controller" in an application

1) Using Controller at SingleFileUploadController, gives correct result in jsp and when used RestController instead of Controller in SingleFileUploadController, it is not directing to jsp. Why?
2) Is it possible to use both at same time?
reference:
http://memorynotfound.com/spring-mvc-file-upload-example-validator/
Thanks
Harshal
Because RestController is for controllers who don't forward to views. Their return value is sent as the response body.
Yes, it's possible to have Controllers and RestControllers in the same webapp. If you want some methods of your controller to return views, and some others to return response bodies (i.e. act as in a RestController), then use #Controller, and annotate your "REST" methods with #ResponseBody.
To answer the question in regards to #Controller and #RestController being together.
First controller:
#RestController //specify that this class is a restful controller
#RequestMapping("/api")
public class RestHomeController {
Second Controller
#Controller //specify that this class is a controller
#RequestMapping("/")
public class HomeController {
#Controller tells the api to return ModelAndView Object which contains the name of your view hence the jsp file to view, while #RestController returns serialized response.
No you cannot have them both, controller is either annotated with one of them but as #JB Nizet mentioned you can use #Controller and #ResponseBody to achieve the functionality for #RestController for specific API , anyway this was the trend used since the support for RestController was not there before spring 4.

Passing in a date to WebAPI - No HTTP resource was found that matches the request URI

I have a GET request that I make in Chrome Postman. It looks like the following:
http://localhost/WCAPI/Lookup/WCClassDesc/State/AL/Class/7230/DescCode/00/EffDate/2016-04-13
Can anybody see why I would get this response in Postman?
{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost/WCAPI/Lookup/WCClassDesc/State/AL/Class/7230/DescCode/00/EffDate/2016-04-13'.",
"MessageDetail": "No action was found on the controller 'WCClassDesc' that matches the request."
}
My code is:
using System;
using System.Web.Http;
/// <summary>
/// API for loading WCClassDescription which is shown on the PremByClass page.
namespace WCAPI.Controllers.Lookup {
[RoutePrefix("Lookup/WCClassDesc")]
public class WCClassDescController : ApiController {
[Route("State/{State}/Class/{Class}/DescCode/{DescCode}/EffDate/{EffDate}")]
public Models.Lookup.WCClassDesc Get(string ClassState, string ClassCode, string DescCode, DateTime EffDate) {
var desc = (new Premium.BLL.WCClassDesc()).GetCurrentWCClassDesc(ClassState, ClassCode, DescCode, EffDate);
var WC = AutoMapper.Mapper.Map<Models.Lookup.WCClassDesc>(desc);
return WC;
}
}
}
Any help or direction would be greatly appreciated.
Jason
There are multiple problems with your code, let's start from the URI:
Assuming you are testing your application using the root path of your host (localhost) and following your definition of RoutePrefix and Route attributes, the correct URI for your resource is the following:
http://localhost/Lookup/WCClassDesc/State/AL/Class/7230/DescCode/00/EffDate/2016-04-13
That's because there is no WCAPI defined in your RoutePrefix attribute.
The other problem is related to the route parameter mapping, you defined you parameters as {State} and {Class}, but then you are asking for ClassState and ClassCode inside your method.
Rename those parameters to match the ones defined in your route, or else Web API will not map them to your method parameters.

Does JSON always have to match a POJO/Bean and vice versa in spring-mvc Rest?

Every time I call my REST API sending a JSON through PUT, for instance, and there is some different property on it, I got 400 (Bad Request) as a result.
Is there any way to configure spring-mvc to ignore no existent properties when JSON and my Class do not perfectly match?
Here is a sample of a method on my controller:
======
#Transactional
#RequestMapping(method=RequestMethod.PUT, value="/include",
consumes=MediaType.APPLICATION_JSON_VALUE,
produces={MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_XML_VALUE })
public #ResponseBody ResponseEntity<Client>
inserirClienteSemRedeSocial(#RequestBody Client client) {
clientDAO.insert(client);
return new ResponseEntity<Client>(client, HttpStatus.OK);
}
you can add to your Pojo:
#JsonIgnoreProperties(ignoreUnknown=true)
which will ignore unknown fields
javadoc

Dynamic Routing with Web API

I have a WebAPI controller with a Get method as follows:
public class MyController : ApiController
{
public ActionResult Get(string id)
{
//do some stuff
}
}
The challenge is that I am attempting to implement WebDAV using Web API. What this means is that as a user browses down a folder structure the URL will change to something like:
/api/MyController/ParentFolder1/ChildFolder1/item1.txt
Is there a way to route that action to MyController.Get and extract out the path so that I get:
ParentFolder1/ChildFolder1/item1.txt
Thanks!
"Dynamic" route is not a problem. Simply use wildcard:
config.Routes.MapHttpRoute(
name: "NavApi",
routeTemplate: "api/my/{*id}",
defaults: new { controller = "my" }
);
This route should be added before default one.
Problem is that you want to end URL with file extension. It will be interpreted as static request to .txt file.
In IIS7+ you can work around that by adding line in web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
Don't forget that if you use MyController, then route segment is just "my"
Use the NuGet package "AttributeRouting Web API". You can specify specific routes for each action, including dynamic parameters.
I was just dealing with this so try it out, and come back if you need more help.

Configure Spring MVC with AngularJS

I would like to be able to use Spring MVC as REST server and AngularJS on client side.
I have several urls for REST :
/rest/products
/rest/products/{id}
And i have several urls for the UI :
/shop/products
/shop/products/{id}
Since it is AngularJS which do the trick on client side, i just want to be able to redirect all default ui urls (not the rest ones) to the index.html file used by AngularJS.
So, in Spring MVC configuration, i would like to be able to do something like that :
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "com.mypackage.web")
public class WebAppConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/**").setViewName("index");
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
With that, i want to delegate all the UI urls handling to AngularJS.
I also want that if the user writes a bad url in the browser he would be redirected by Spring MVC on the index.html file and it will be AngularJS which will do the redirect on the error ui page. I have seen several projects on the web with a single index.html file, but no one handle this error case.
I have been struggling a lot of time trying to do this trick but i can't find a solution.
So my question is : how can i do that ? and more generally, am i wrong with this Spring MVC-AngularJS wanted configuration ?
Very important : I use Spring MVC 3.2 and Tomcat 7.34 without web.xml (full Servlet 3.0)
Thanks a lot.
Maybe it is possible to solve it via $routeProvider:
$routeProvider.when('/redirect/:redirectParams', {templateUrl: 'partials/homePartial', controller: redirectController});
$routeProvider.when('/home', {templateUrl: 'partials/homePartial', controller: homeController});
$routeProvider.when('/someRoute', {templateUrl: 'partials/somePartial', controller: someController});
$routeProvider.when('/error/', {templateUrl: 'partials/errorPartial', controller: errorController});
$routeProvider.when('/error/:errorMessage', {templateUrl: 'partials/errorPartial', controller: errorController});
$routeProvider.otherwise({redirectTo: '/error'})
Just let the $routeProvider redirect to an error page when the route was not found.
Edit:
I've added a redirectController in the above example. This controller will read the $routeParams, in this case $routeParams.redirectParams and use $location to change the route to /error.
Spring just redirects to http://host:port/index.html/#/redirect/error=blabla. You could and should probably finetune this and support multiple routeParams.
In Spring you would have basically three request mappings:
REST request mapping
index.html request mapping
other urls request mapping
To redirect all other requests:
#RequestMapping(value = "{path}", method = RequestMethod.GET)
public String redirect(#PathVariable String path) {
String route = null;
if (path.equals("/") || path.startsWith("/index.html")) {
// load index.html
} else {
route = "redirect:/index.html/#/redirect/" + path;
}
return route;
}
I think you can write an Interceptor which allows some known URLs like /rest/, /resources/, /webjars/* and for any other URLs redirect to index.html.
Try using urlrewritefilter
This should do the work for you. You'll have to configure/add it in your web.xml to every url would be handled and you can manipulate it to redirect to the index.html
I know its a bit late but in case someone run into the same trouble here's the URL filter sample put in your classpath urlwrite.xml
You can set redirection of certain urls you want to filter.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
"http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<!-- Configuration file for UrlRewriteFilter http://www.tuckey.org/urlrewrite/ -->
<urlrewrite>
<rule>
<note>
The rule means that requests to /test/status/ will be redirected
to
/rewrite-status
the url will be rewritten.
</note>
<from>/index.ipxs/directory</from>
<to type="redirect">/index.ipxs/marketplace</to>
</rule>
<rule>
<from>/index.ipxs/faq</from>
<to type="redirect">/index.ipxs/marketplace</to>
</rule>
<rule>
<from>/index.ipxs/marketplace</from>
<to type="redirect">/iPlexus/index.ipxs</to>
</rule>
</urlrewrite>

Resources