Check if Thymeleaf template url contains string - spring

How can I check if this URL 'http://localhost:8080/employees/subordinates/1' contains the string 'subordinates'? I'm trying to make the presence of an anchor conditional upon the URL containing the phrase. This is what I've been hoping to achieve.
<div th:if="${#strings.contains(#httpServletRequest.requestURI, 'subordinates')}">
employee directory
</div>

Yes, the workaround you mention in the comments is the way to do it.
The #request, #response, #session, and #servletContext expression utility objects are no longer available in Thymeleaf 3.1. According to this issue:
The #request, #response, #session and #servletContext expression utility objects should be removed from the Standard Dialect, both for security reasons (in order to avoid direct access to potentially unsafe properties such as request parameters) and also due to the fact that these are currently bound to the javax.* Servlet API, and generalizing the web interfaces in the Thymeleaf core in order to support jakarta.* and other web technologies would not be compatible with these specific objects still being available.
The article Thymeleaf 3.1: What’s new and how to migrate recommends adding to your model, at the controller level, the specific pieces of information your templates need from these objects. For example, you can add the following to your controller:
#ModelAttribute("requestURI")
public String requestURI(final HttpServletRequest request) {
return request.getRequestURI();
}
And use the attribute in your template this way:
<div th:if="${#strings.contains(${requestURI}, 'subordinates')}">
employee directory
</div>

Related

How do I test form submission with Spring MVC test?

Most of my experience with creating controllers with Spring are for REST controllers that consume JSON formatted requests. I've been searching for documentation on how to do testing for form submission, and so far this is how I understand it should go using MockMvc:
MvcResult result = mockMvc.perform(post("/submit")
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
However, I'm not sure how to map the form parameters to a model object. I've seen the #ModelAttribute annotation pop up in my searches but I can't figure out how it should be used for mapping. In addition, this quick start guide from the official documentation does not elaborate on how things like th:object and th:field translate to HTML and subsequently to URL encoded form.
I have my controller code similar to the following:
#PostMapping('/submit')
def submit(#ModelAttribute WriteUp writeUp) {
//do something with writeUp object
'result'
}
I discovered through trial and error that my specific problem might have been Groovy specific. There test code and the controller code, it turns out, have no issues. To reiterate, for testing form submission, use the param method through perform method of MockMvcRequestBuilders. Another thing to note is that this doesn't seem to work if content type is not specified. Here's a sample test code that works for me:
MvcResult result = webApp.perform(post("/submit")
.contentType(APPLICATION_FORM_URLENCODED) //from MediaType
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
As you can see, it's not much different from what I posted originally. The controller code is pretty much just the same, with #ModelAttribute working just fine.
The problem with my setup though was that since I was using Groovy, I assumed that getters and setters were automatically generated in my WriteUp class. Here's how the WriteUp class looked originally:
class WriteUp {
private String title
private String description
}
I haven't written code in Groovy for a while, and the last time I did, classes like the one above can be assumed to have getters and setters implicitly. However, it turns out that is not the case. To solve my specific issue, I updated the access modifier in the fields to be default (package level):
class WriteUp {
String title
String description
}
I've seen the #ModelAttribute annotation pop up in my searches but I
can't figure out how it should be used for mapping.
When you mark your writeUp object with #ModelAttribute, then the Spring container populates the parameters (like title, description, etc..) from HttpServletRequest object & injects the object to the controller method, when the request comes to the server from the client (could be a Browser or MockMvc unit test client or anything else).
Also, few other basic points for your quick understanding:
(1) Controller methods are mapped to an URI and RequestMethod (like POST/GET/DELETE/PUT et..) like shown below:
#RequestMapping(value="/submit", method=RequestMethod.POST)
public String submit(#ModelAttribute WriteUp writeUp) {
//Call the service and Save the details
model.addAttribute("Writeup details added successfully");
return "writeUpResult"; //Returns to the View (JSP)
}
(2) #ModelAttribute will be mapped to an object (like your writeUp) for http POST/PUT requests where the html formd data is part of http body.
(3) #RequestParam or #PathParam will be used for http GET requests where the parameters are part of URL (i.e., not part of http body).
You can look here for understanding the DispatcherServlet request handling & Spring MVC basic web flow.

Default handler mapping for annotation based spring project

I am new to spring framework. Even I dont have any deep concept about annotation.
I am developing a very small application using spring mvc 3 framework and also I used annotation.
I have a confusion. I have one spring-servlet.xml. Here I have not defined any handler mapping. But still it is working. So must be there some default handler mapping. Can you please let me what is this default handler mapping and how I can override it so that I do some customization.
It is all explained in: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config
Also see this question: How to use default-servlet-handler and Where to put default-servlet-handler in Spring MVC configuration
Spring 3.1 and later doesnt need DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter declaration in the [servelt-name]-servlet.xml
These links might help:
Spring Controller to handle all requests not matched by other Controllers
https://dzone.com/articles/using-the-spring-requestmapping-annotation
I had the same problem that I just resolved so I have confirmed the approach below works, although this is with annotations rather than an XML configuration.
You specify URL prefixes at the controller class level and include a request mapping annotation for ** to ensure you match on anything that falls through your other handlers for this class. There's really nothing special or default about this handler other than the fact that you're defining a handler that is guaranteed to match everything under the class level mappings.
Note: This is not magic. Your handlers are still subject to Spring's ordering algorithm regarding the "best match". It would be nice to have an annotation providing for a true default when nothing else matches handler, especially in cases with complex mappings where "**" is useful outside of this catch-all handler. The basic implementation is:
#RestController
#RequestMapping(value={"/path1/","/path2/"})
public class MyRestController {
#RequestMapping("/subpath")
String matchedRequestHandler () {
return "This matches /path1/subpath and /path2/subpath.";
}
#RequestMapping("**")
String unmatchedRequestsHandler () {
return "This matches everything else.";
}
}
In my actual use case, I needed to handle arbitrary paths to resources inside of the URL pattern and therefore needed to support a variable number of directories. Ideally, that would be handled using a pattern such as:
"/base/{optionaldir}/**/{entityName}/{describeVar:describe.json}"
which works fine by itself, but it isn't compatible with a default handler bound to "**" since the "**" mapping is calculated by Spring as a better match for these types of requests.
Instead, I had to add a bunch of separate entries to my request mapping to support the arbitrary paths within the URL pattern, e.g.
value={"/base/{optionaldir}/{entityName}/{describeVar:describe.json}",
"/base/{optionaldir}/*/{entityName}/{describeVar:describe.json}",
"/base/{optionaldir}/*/*/{entityName}/{describeVar:describe.json}",
"/base/{optionaldir}/*/*/*/{entityName}/{describeVar:describe.json}"
}
Alternatively, I could have handled everything with a "**" mapping and parsed the URL myself, but that kind of defeats the purpose of using request mappings with path variables. Hopefully Spring's capabilities will evolve in this area in the future.

Spring controller declaration

I am wondering what are the requirements for a method (or a class) to be labeled with #Controller? As for input arguments, the Spring tutorial seems to indicate that methods can sometimes take in nothing and sometimes take in a Model object:
http://blog.springsource.com/2011/01/04/green-beans-getting-started-with-spring-mvc/
And this:
Spring MVC Controllers Return Type
seems to indicate that the return type can be a String or a ModelAndView. I tried to look that up in the official documentation but couldn't find much info. I presume there must be some requirements. Any pointers?
In Spring Class is marked as #Controller, methods are marked as #RequestMapping handling specific request based on parameter,url path, accept header etc.
Spring MVC is highly flexible and allows you to have many return types see spring reference see "Supported method return types" section on the same page.
Also spring-mvc-3-showcase blog

ASP.NET Web API Deserialize Query Parameters into Nested POCO Action Parameter

Already checked this question but didn't answer.
Background
I have a fully functional RESTful web service written using ASP.NET Web API and it currently supports CORS effectively for cross-origin access from browsers that support CORS. Problem is that current business needs require support of browsers that don't support CORS. I am adding JSON-P support to my web service in addition to supporting CORS and through the magic of action selectors and type formatters, my actual web service code hasn't changed....yet.
Currently I use nested POCO objects (objects that contain other objects) as parameters, for example, for my Post actions. Since I'm supporting XML and JSON incoming, the POST data gets deserialized nicely into the POCO objects, since both XML and JSON support nested deserialization. But to support JSON-P, I have to now emulate a POST through Query Parameters. Getting to the Post action method is successful via an httpMethod Query Parameter and a custom action selector.
Question(s)
First of all, and I ask this after reading responses to other questions, will the registered type formatters even access the Query Parameters for deserializing if I have no request body? The JSON-P request is going to be a simple GET request with no body, so I'm not even sure if it is possible to have a POCO in my action parameter and have it deserialized with a GET request and only Query Parameters.
EDIT: Looks like I may be able to do some MediaTypeFormatter magic with a custom formatter and using the QueryStringMapping. Not sure yet though.
Second, is it possible to deserialize Query Parameters into nested properties of the POCO object? And if so, what is the naming convention for Query Parameters to do this? For example XML of Bob would get deserialized into Message.User.FirstName if the action parameter was of type Message.
EDIT: FormUrlEncodedMediaTypeFormatter has some of the functionality that I want if I could just redirect it to use the Query String instead of the body. But I also don't want a JToken object -- I'd like my POCO, but I think I can deserialize a JToken with JSON.NET. So I'm probably going to steal the code from FormUrlEncodedMediaTypeFormatter and the relate internal class FormUrlEncodedJson to make a custom formatter. Just need to make sure question #1 is possible first.
Example POCOs
public class User
{
public string FirstName { get; set;}
}
public class Message
{
public User User { get; set; }
}
Example "standard" RESTful POST
POST /api/messages
Content-Type: text/xml
<Message><User><FirstName>Bob</FirstName></User></Message>
Example Hypothetical JSON-P Simulated POST
<script type="text/javascript"
src="https://api.mydomain.com/api/messages?callback=MyCallback&httpMethod=Post&User.FirstName=Bob">
</script>
EDIT: Overall Goal: I'm trying to leave the action methods alone right now if possible since they currently handle RESTful CORS-enabled requests. My goal is to add JSON-P support to the calls without changing the method signature. I've got that mostly accomplished; all I have left is being able to deserialize the Query Parameters into the action method parameters when it's a JSON-P request.
Try adding [FromUri] to your action definition, i.e.:
public HttpResponseMessage YourAction([FromUri] YourModel model)
{
...
}
At this point in time it seems that I must create two different paths in the API. Because of the way request parameter deserialization works, and model binding vs. media type formatters, and the lack of a hook in this particular area, I cannot have one single Web API method and have the parameters taken from either the query string or the content based upon various request factors.

spring mvc form handling without using spring tag

Recently, I have been researching a new framework for the purpose of building a web-application. To this end, I wanted to try out Spring MVC. Of the many parameters for evaluating a framework, one is that I don't want to be bound to the tag libs associated with the framework to make use of the HTTP request parameter -> Java bean translation. The Spring MVC documentation repeatedly mentions that it is possible to do view related things with only JSTL and no Spring tags, however, I haven't found a way to get the Request-to-Bean translation feature [SimpleFormController] to work without Spring tags.
As of now, the only way seems to extract the request parameters one by one and set to my bean. Is there any way to perform this translation w/o using framework dependent tags?
I appreciate your inputs!
I use Spring Web MVC without Velocity templates (non-JSP templating). To answer your question, you need to understand how Spring performs data binding. Basically, it's all in the name you give your input elements. E.g
<input name="properytOne" value="1" type="hidden">
<input name="properytTwo" value="2" type="hidden">
<input name="rich.property3" value="3" type="hidden">
will bind values to an object like this
class CommandOne {
private String propertyOne;
private String popertyTwo;
private CommandTwo rich;
// Getters and setters
}
class CommandTwo {
private String propertyThree;
// Getters and setters
}
You also have to be sure to instantiate your command object, but that will be handled in your SimpleFormController.
Spring tags are completely optional.
Read chapter 15, 16, and 17 of the Spring Reference Document You can use annotations to retrieve request parameters with your controller (see section 15.3).
As per my understanding, what you are trying to achieve is Binding your form to your Bean Class, which is very nicely implemented in JSF. JSF works on component architecture and very easy to start with, plus it has many component builers available such as primefaces, omnifaces, icefaces, openfaces, etc. Reusability of self-designed components can help you a lot in specific projects. Try giving a chance to JSF. Thanks, hope this was helpful.

Resources