3

I would like to test the spring controller below, which reads http request attributes and acts on them. I am able to trigger the controller code below by typing localhost:8080/someURL into my web browser. But the result is {"id":1,"content":"null and null and null"}, which indicate null values in the named request attributes. How do I send a request to a named url like localhost:8080/someURL which contains values for the specified request attributes, so that I can confirm that the receiving controller code works properly?

Here is the code for the controller:

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPa    ram;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Controller
public class SomeController {

    private final AtomicLong counter = new AtomicLong();

    @RequestMapping(value = "/someURL", method=RequestMethod.GET)
    public @ResponseBody Greeting receiveSMS(HttpServletRequest req){
        String att1 = (String) req.getAttribute("att1");
        String att2 = (String) req.getAttribute("att2");
        String att3 = (String) req.getAttribute("att3");
        String total = att1 + " and " + att2 + " and " + att3;
        return new Greeting(counter.incrementAndGet(), String.format(total));
    }

    }  

Note: I am trying to recreate in Spring the PHP functionality that is given in the script at the following link. I have not written this kind of code below, if I am framing the question poorly, I would appreciate advice for reframing it. Along with a link to any example solution such as a JUNIT or other means by which to recreate the request.

5
  • A request will never contain any attribute if it comes from the browser. The only way it can have attributes is if some other resource places these attributes in the request and then forwarded (or included) to this controller. Or if some filter or interceptor on the server placed them before. Commented Dec 27, 2015 at 22:46
  • So, either there is such a resource before, and you should test that resource or write a unit test, or there is bo such resource, the request is supposed to come from the browser directly, and the code is then incorrect. Commented Dec 27, 2015 at 22:48
  • @JBNizet This is a url that will be put into a web service from a third party. Instead of replying with the total string, I will instead pass the three request attributes into an algorithm. It was just easier to send them as a response for testing purposes. If you are saying it is better to SYSO the total string, I can do that, but I still need to send a request to the url containing the named attributes. How can I do this? Commented Dec 27, 2015 at 22:50
  • You can't pass attributes from the outside. Period. There is no way any client can ever pass attributes to your controller. You need to make them parameters, or headers, or path variables, i.e. something that can be sent using HTTP. Commented Dec 27, 2015 at 22:55
  • @JBNizet Thank you for guiding this to an answer. Commented Dec 27, 2015 at 23:57

3 Answers 3

2

Request attributes are server-side only constructs. Try using request parameters instead:

@RequestMapping(value = "/someURL", method = RequestMethod.GET)
public @ResponseBody Greeting receiveSMS(@RequestParam("att1") String att1, @RequestParam("att2") String att2, @RequestParam("att3") String att3){
    String total = String.format("%s and %s and %s", att1, att2, att3);
    return new Greeting(counter.incrementAndGet(), total);
}

Then send a request of the form:

http://localhost:8080/someURL?att1=value1&att2=value2&att3=value3

And you should be able to read the values that you are trying to pass.

Sign up to request clarification or add additional context in comments.

5 Comments

This is a url that will be put into a web service from a third party. Instead of replying with the total string, I will instead pass the three request attributes into an algorithm. It was just easier to send them as a response for testing purposes. If you are saying it is better to SYSO the total string, I can do that, but I still need to send a request to the url containing the named attributes. How can I do this?
@CodeMed the problem is not with the output. The problem is that attributes are a purely-server-side servlet API thing. They're not part of the HTTP protocol. There is no way to pass attributes from the outside. Read my comments.
@CodeMed Exactly as JB Nizet says. Attributes are not passed in by the client. But parameters and headers are. So figure out what exactly you're trying to read from the request, and use the appropriate method to read the info.
@JBNizet I added a note to the end of my OP showing a link to a PHP script which I am trying to mimic in Spring. I do not know PHP, but my translation of it was that it contained three request parameters. The spring controller code in my OP would be used to receive the same messages that the PHP code in the link in my OP is supposed to receive. Does this help clarify what I am trying to learn? I would be happy to reframe my question if you feel that I am not asking well enough.
@CodeMed my translation of it was that it contained three request parameters: that's the correct translation. Those are request parameters. Not request attributes. Parameters and attributes are completely different things.
1

Checkout Spring MVC Test framework - instead of manually fire some URLs write unit tests instead.

Regarding your note

Yes, that's parameters. In php you have $_GET and $_POST or (if you don't care about the method) simply $_REQUEST for accessing the request parameters. Recode from getAttribute() to getParameter() or put them in your method signature using @RequestParam annotation.

@RequestMapping(value = "/receiveSMS", method=RequestMethod.GET)
public @ResponseBody Greeting receiveSMS(@RequestParam("from") String from,
       @RequestParam("to") String to, @RequestParam("body") String body){

}

Now you can try http://localhost:8080/yourapp/receiveSMS?from=me&to=you&body=stackoverflow

Sidenote:

If you want that info send from the client, you should use getParameter() calls instead.

2 Comments

I added a note to the end of my OP clarifying my question based on the comments. Does this help you identify the solution? I have not written JUNIT tests before, but I can easily add JUNIT to my gradle.build if you can suggest specific code that would accomplish what the link in the NOTE at the end of my OP accomplishes.
The above works for GET, but it has to work for POST. If I change GET to POST in your code below, how do I test a post request? When I use the url from the browser, the log shows an error indicating that an unsupported GET was requested.
-1

test something like :

http://localhost:8080/someURL?att1=value1&att2=value2&att3=value3

It will show you the value1, value2 and value3 passed into the URL...

2 Comments

No, it won't. You're confusing attributes with parameters.
Oh ! Bien vu ! I'm not confusing but i'm a little bit tired... :p Thanks for the pointer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.