How does a servlet get data from another servlet? - java

My problem like this:
I have two servlets:
servlet_A: http://localhost:8080/test/servlet_wait_for_response
servlet_B: http://localhost:8080/test/servlet_send_data?data=xxx
1. I use Firefox invoking servlet_A, and the servlet_A does nothing but wait;
2. I use Chrome invoking servlet_B, and send "helloworld" to the server, for example: http://localhost:8080/test/servlet_send_data?data=helloworld
3. servlet_B get the message "helloworld", then send this message to servlet_A;
4. servlet_A get the message "helloworld" from servlet_B, then response this message to Firefox.

I got an answer like below:
static String msg = null;
#RequestMapping(value = "/wait_for_data", method = RequestMethod.GET)
#ResponseBody
public String waitData() throws InterruptedException{
while(msg==null){
TimeUnit.SECONDS.sleep(1);
}
return msg;
}
#RequestMapping(value = "/send_data", method = RequestMethod.GET)
#ResponseBody
public String sendData(String data){
msg = data;
return "OK";
}

Related

How to solve error code "405" on API call with testing?

I'm getting error code "405" while testing my API calls on run mode in IntelliJ. However when I test the API cal; with the same parameters in Postman it works.
I'm programming a jukebox where an user has to log in in order to use it. The login form works and when i try to log in with Postman it also logs in succesfull. However when i run my code on IntelliJ it gives me error code "405", which means "Method not allowed".
My userController class code which works:
#PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String login(#RequestBody MultiValueMap<String, String> body){
String email = body.getFirst("email");
String username = body.getFirst("username");
String password = body.getFirst("password");
return userService.loginUser(email, username, password);
}
My functional testing code(also works because my other GET methods in my API tests works):
public class FunctionalTest {
#BeforeClass
public static void setup() {
String port = System.getProperty("server.port");
if (port == null) {
RestAssured.port = Integer.valueOf(8080);
}
else{
RestAssured.port = Integer.valueOf(port);
}
String basePath = System.getProperty("server.base");
if(basePath==null){
basePath = "/";
}
RestAssured.basePath = basePath;
String baseHost = System.getProperty("server.host");
if(baseHost==null){
baseHost = "http://localhost";
}
RestAssured.baseURI = baseHost;
}
}
And finally my code for testing the POST method for logging in:
//User control
#Test
public void checkLogin(){
given()
.param("email", "123")
.param("username", "123")
.param("password", "123")
.when()
.get("/login")
.then()
.statusCode(200);
}
Hope anyone can help me solve this problem.
Thanks in advance!
405 means method not allowed. This is happening because you are exposing a POST operation (#PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) but trying to consume by means of a GET: .when().get("/login")

How to handle requests that contain forward slashes?

My URL request is http://localhost:8080/login/verify/212,32,/cntv5tag07rmy791wbme7xa8x,/SSNZclzqhhH7v6uHIkUsIcPusKo=
I need get the following part: **212,32,/cntv5tag07rmy791wbme7xa8x,/SSNZclzqhhH7v6uHIkUsIcPusKo=**.
The following code doesn't work:
#RequestMapping(value = "/login/verify/{request:.+}", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public ResponseEntity verifyLogin(#PathVariable(value = "request") String request)
throws InvalidSignatureException
{
}
Error: HTTP Status 404.
Spring can't handle this request.
To match the uri with the slashes, use the double *
#RequestMapping(value = "/login/verify/**",
Then, in the body to get the value, you will use
String str = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)
Sample code:
#RequestMapping(value = "/login/verify/**", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public ResponseEntity verifyLogin(HttpServletRequest httpServletRequest) throws InvalidSignatureException {
String str = (String) request.getAttribute( HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)
}
You have forward slashes in your url and those strings will be considered as path variables. Try the following code if there is a possibility that you'll have only 3 path variables. Please have a look at here and here
#RequestMapping(value = {"/login/verify/{string1:.+}",
"/login/verify/{string1:.+}/{string2:.+}",
"/login/verify/{string1:.+}/{string2:.+}/{string3:.+}"}, method = RequestMethod.POST)
public ResponseEntity verifyLogin(HttpServletRequest request, HttpServletResponse httpresponse,
#PathVariable("string1") String string1,
#PathVariable("string2") String string2,
#PathVariable("string3") String string3) {
System.out.println("***************************************************I am called: "+string1+" "+string2+" "+string3);
}
Try this URL instead: http://localhost:8080/login/verify?req=212,32,/cntv5tag07rmy791wbme7xa8x,/SSNZclzqhhH7v6uHIkUsIcPusKo=
And handle it like this:
#RequestMapping("/login/verify")
public String test(#RequestParam("req") String data) {
//'data' will contains '212,32,/cntv5tag07rmy791wbme7xa8x,/SSNZclzqhhH7v6uHIkUsIcPusKo='
String params[] = data.split(",");
}

How to send POST request to relative URL with RestTemplate?

How can I send a POST request to the application itself?
If I just send a relative post request: java.lang.IllegalArgumentException: URI is not absolute.
#RestController
public class TestServlet {
#RequestMapping("value = "/test", method = RequestMethod.GET)
public void test() {
String relativeUrl = "/posting"; //TODO how to generate like "localhost:8080/app/posting"?
new RestTemplate().postForLocation(relativeUrl, null);
}
}
So using the example above, how can I prefix the url with the absolute server url path localhost:8080/app? I have to find the path dynamically.
You can rewrite your method like below.
#RequestMapping("value = "/test", method = RequestMethod.GET)
public void test(HttpServletRequest request) {
String url = request.getRequestURL().toString();
String relativeUrl = url+"/posting";
new RestTemplate().postForLocation(relativeUrl, null);
}
Found a neat way that basically automates the task using ServletUriComponentsBuilder:
#RequestMapping("value = "/test", method = RequestMethod.GET)
public void test(HttpServletRequest req) {
UriComponents url = ServletUriComponentsBuilder.fromServletMapping(req).path("/posting").build();
new RestTemplate().postForLocation(url.toString(), null);
}
If you want to refresh application.properties, you should AutoWire the RefreshScope into you controller, and call it explicitly, it make it much easier to see what it going on.
Here is an example
#Autowired
public RefreshScope refreshScope;
refreshScope.refreshAll();

How to return an error message to the browser when condition fails in java?

I am sending just an message when condition fails.
#ResponseBody
#RequestMapping(value = "/id", method = RequestMethod.GET)
public String downloadFormDataAsPdf(
#PathVariable("id") String id){
if(!id.isEmpty())
{
// code
}
else{
return "You are not allowed"
}
}
I am writing this under requestMapping GET method in the controller..But what i am getting is only a some part of error message is displayed in the browser.CAn i know why .I need to get full text message if condition fails.

405 Method Not Allowed with Spring

I have the following test for an HTTP endpoint:
public static final String DATA_PARAMETER = "data";
public static final String ID_PARAMETER = "id";
public static final String VIDEO_SVC_PATH = "/video";
public static final String VIDEO_DATA_PATH = VIDEO_SVC_PATH + "/{id}/data";
#Multipart
#POST(VIDEO_DATA_PATH)
public VideoStatus setVideoData(#Path(ID_PARAMETER) long id, #Part(DATA_PARAMETER) TypedFile videoData);
#Test
public void testAddVideoData() throws Exception {
Video received = videoSvc.addVideo(video);
VideoStatus status = videoSvc.setVideoData(received.getId(),
new TypedFile(received.getContentType(), testVideoData));
assertEquals(VideoState.READY, status.getState());
Response response = videoSvc.getData(received.getId());
assertEquals(200, response.getStatus());
InputStream videoData = response.getBody().in();
byte[] originalFile = IOUtils.toByteArray(new FileInputStream(testVideoData));
byte[] retrievedFile = IOUtils.toByteArray(videoData);
assertTrue(Arrays.equals(originalFile, retrievedFile));
}
I'm trying to implement the requirements defined by this test with the following endpoint defined in Swing:
#RequestMapping(method = RequestMethod.POST, value = "/video/{id}/data")
public void postVideoData(#PathVariable("id") long videoId,
#RequestParam("data") MultipartFile videoData) throws IOException {
if (videoId <= 0 || videoId > videos.size()) {
throw new ResourceNotFoundException("Invalid id: " + videoId);
}
Video video = videos.get((int)videoId - 1);
InputStream in = videoData.getInputStream();
manager.saveVideoData(video, in);
}
The problem is that I get a "405 Method Not Allowed" error. What am I doing wrong so that my POST method is not being recognized?
The problem is that the client interface expects a VideoStatus object returned from the server. I declared the method on the server side to return void.
I don't know if you already fix your problem, but I got the same error, because I am new with Retrofit too :).
The solution for me, was to put an Annotation to specify the response content type, in my case
#ResponseBody
Another change that I must did, was to change void for a custom status.
Hope this helps or at least gives you a light.
Rgds.
I had the same issue. RetroFit request calls must have either a return type or Callback as last argument.
So in the RetroFitted API:
#POST("/path")
public Void saveWhatever(#Body Whatever whatever);
Than in the controller it must be :
#RequestMapping(value = "/path", method = RequestMethod.POST)
public #ResponseBody Void saveWhatever(#RequestBody Whatever whatever) {
repository.save(whatever);
return null;
}

Categories