We do have a service that generates pdf documents dynamically(each request - slightly different PDF document). So I have to create a contract test for that service.
Problem statement
STUB side should return a predefined pdf file as a byte array. - OK
SERVER side should not check the response in assertions, or at least check if it matches by some regexp. - NOT WORKING
Here is my contract.groovy
import org.springframework.cloud.contract.spec.Contract
[
Contract.make {
request {
method "GET"
urlPath("/pdfEndpoint")
}
response {
status 200
headers {
contentType(applicationPdf())
}
body(value(
consumer(fileAsBytes("staticFileToSentOnStubResponse.pdf")),
producer(regex(nonBlank())) /*the issue is with that line*/
))
}
}
]
GenereatedTestClass.java
#Test
public void contractPdf() throws Exception {
// given:
MockMvcRequestSpecification request = given();
// when:
ResponseOptions response = given().spec(request)
.get("/pdfEndpoint");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).matches("application/pdf.*");
// and:
String responseBody = response.getBody().asString();
assertThat(responseBody).isEqualTo("^\\s*\\S[\\S\\s]*"); // .isEqualTo() but needed matches()
}
Is there any way to update the groovy file to have in the generated class the folowing assertion
assertThat(responseBody).matches("^\\s*\\S[\\S\\s]*");
instead of
assertThat(responseBody).isEqualTo("^\\s*\\S[\\S\\s]*");
UPDATE:
Also, I have noticed that it generates assertThat(..).isEqualTo() in case i have contentType(applicationPdf()) in the response headers.
If I put 'application/json' instead - it will work as expected.
Resources:
org.springframework.cloud:spring-cloud-dependencies - Hoxton.SR8
java11
I try create response from file for testing elasticsearch service
def "FounderHint"() {
setup:
URL url = getClass().getClassLoader().getResource("elastic_response/elastic-founders-hint-response.json")
SearchResponse response = new SearchResponse().readFrom(url.openStream()) // this is a 40 line error
when: "we ask for hint"
elasticClient.search(any()) >> response
metrics.measureHintSearchTime(_) >> response
then: "we get list of ObjectHint"
List<ObjectHint> result = advancedSearchFilter.founderHint("але").collect(Collectors.toList())
result[0].inn == "323500905646"
result[0].name == "Алешина Екатерина Леонидовна"
but i get error -
No signature of method: org.elasticsearch.action.search.SearchResponse.readFrom() is applicable for argument types: (java.io.BufferedInputStream) values: [java.io.BufferedInputStream#19f135ca]
Possible solutions: readFrom(org.elasticsearch.common.io.stream.StreamInput), readFrom(org.elasticsearch.common.io.stream.StreamInput), readFrom(org.elasticsearch.common.io.stream.StreamInput)
groovy.lang.MissingMethodException: No signature of method: org.elasticsearch.action.search.SearchResponse.readFrom() is applicable for argument types: (java.io.BufferedInputStream) values: [java.io.BufferedInputStream#19f135ca]
Possible solutions: readFrom(org.elasticsearch.common.io.stream.StreamInput), readFrom(org.elasticsearch.common.io.stream.StreamInput), readFrom(org.elasticsearch.common.io.stream.StreamInput)
at ru.esphere.informator.refbook.retriever.hint.SearchExternalHintServiceTest.test external hint method for receive correct result(SearchExternalHintServiceTest.groovy:40)
SearchResponse is a class elasticsearch and it does not have setters, are there other ways to create a response or where did I make a mistake?
BufferedInputStream stream = url.openStream()
SearchResponse response = new SearchResponse().readFrom(new StreamInput(stream))
The BufferedInputStream from the first line is transformed into StreamInput, before passing it to readFrom
I have jobs that return a WS.HttpResponse result like:
public class GetMessage extends Job<HttpResponse> {
...
public HttpResponse doJobWithResult() {
HttpResponse resp = WS.url(url).get();
return resp;
}
}
This is how I get the result from the job:
HttpResponse response = await(new GetMessage(params).now());
When I attempt to call getString() or getStream() using the "response" object I'm not getting any data.
If I call getString() in the job on "resp" then it has the data as expected.
It's strange because this worked with Play 1.2.4 - Play 1.2.7.2.
After the await I do have a non null "response" object and I can call getStatus() on it and it returns a 200, but maybe that's the default when WS.HttpResponse is initialized. I'm thinking that maybe I'm getting a new WS.HttpResponse() rather than the one returned from the job.
I found the problem. I was calling getString() to construct an error message that I would log if I got an error response. This was clearing the stream. I'm not sure why it worked the way it was in play <= 1.2.7.2.
Perhaps the InputStream should be closed and throw when calling getStream after getString or getStream have been called?
Here is my Ajax code:
var myJSONObject = {"bindings": [
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}]
};
$.ajax({
url : "ships",
data : myJSONObject,
success : function(data){
GLOBAL.player.startShooting(data);
},
error : function(data) {
console.log("error:", data);
},
dataType : "json",
timeout : 30000,
type : "post"
});
And here is my Java Servlet code:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("im in PSOT");
System.out.println(request.getParameter("myJSONObject"));
StringBuilder sb = new StringBuilder();
BufferedReader br = request.getReader();
String str;
while( (str = br.readLine()) != null ){
sb.append(str);
}
System.out.println(sb.toString());
response.setContentType("application/json");
response.getWriter().write("{\"key\":\"hello\",\"key2\":\"world\"}");
}
The Java servlet returns my Hello World object, but i CANNOT read data in Java Servlet
The console prints out the following:
im in PSOT
null
The last line is an empty string from last println.
I am using Tomcat 7
Can anyone please tell me what i am doing wrong and why i cannot read data in Java Servlet_
The parameter name is not myJSONObject. That's the JS variable name. The parameter names are all the root keys which you have there in your JSON object. E.g.
String bindings = request.getParameter("bindings");
// ...
You'd only need to manually parse it further. You could use Google Gson for this.
As to why the Reader didn't return anything, that's because the request body can be read and parsed only once. Any getParameter() call will implicitly do that. So when you call getParameter() before getReader(), you won't be able to read the request body by the Reader (the same applies for the other way round!). But you don't need it anyway. Just use getParameter() with the proper parameter names.
You'd only need to manually parse it further. You could use Google Gson for this.
As to why the Reader didn't return anything, that's because the request body can be read and parsed only once. Any getParameter() call will implicitly do that. So when you call getParameter() before getReader(), you won't be able to read the request body by the Reader (the same applies for the other way round!). But you don't need it anyway. Just use getParameter() with the proper parameter names.
A normal java file executes only those methods called in the main. But what does a servlet do? I thought maybe it executes down the file but I just tried to split up a HTTP servlets request and response but it doesn't work. What is a neat way of working with a servlet to read an input stream, then execute some functions which can call the response writer method?
Here was my tryout code:
public void requestReader(HttpServletRequest req) {
try {
int len = req.getContentLength();
byte[] input = new byte[len];
ServletInputStream sin = req.getInputStream();
int c, count = 0 ;
while ((c = sin.read(input, count, input.length-count)) != -1) {
count +=c;
}
sin.close();
String inString = new String(input);
int index = inString.indexOf("=");
String value = inString.substring(index + 1);
inputStream = URLDecoder.decode(value, "UTF-8");
} catch (IOException e) {
}
}//end of requestReader
public void responseWriter(HttpServletResponse resp) {
try{
resp.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());
writer.write("Working");
writer.flush();
writer.close();
} catch (IOException e) {
}
}//end of responseWriter
A normal java file executes only those methods called in the main.
A "Java file" does not execute anything. The JVM, started by the java command line tool, executes the main method.
But what does a servlet do? I thought maybe it executes down the file
A servlet runs inside a Servlet Container, e.g. Apache Tomcat, or Jetty. The container itself is started via a main method, it learns about servlet classes in its web.xml file, and it calls the service() method of the servlet when a request arrives.
What is a neat way of working with a servlet to read an input stream, then execute some functions which can call the response writer method?
That's exactly what a servlet does (though the headers of a HTTP request are parsed by the servlet container and passed to the servlet as part of the request object). What are you really trying to do?
If you're not running a servlet container, it makes no sense to use servlets.
No Java class simply executes methods sequentially.
If you want to use multiple methods, you must break up your functionality and explicitly call the other methods you want to use, just like you do in a standalone program.
Servlet execution starts with a request handler, generally doPost or doGet.
Here's a tutorial to read through, but there are countless others--just search for "servlet tutorial".
Methods are never executed sequentially. They are executed WHEN called.
The function of a servlet is to service HTTP requests from a web browser. For this, your servlet must implement a service() method and then call your methods from inside it.
You could also implement doPost() or doGet() but they only respond to the POST and GET commands.
You can start by looking here
Servlets are typically used in the context of a web server. This is in contrast with a "normal Java file" which is typically executed from the command line and starts with the main method.
In order to get your servlet to work, you need to make it part of a Java web application. If you've never done this before, it would be best to follow a tutorial about Java web applications.
Briefly, the doPost, doGet, or service methods of HttpServlet are roughly equivalent to the main method (though with some important differences such as the main method is entered once while service can be entered many times).
When a GET HTTP request comes in, and the servlet is mapped to the path of the request, then the servlet doGet method is called. If it's a POST, then doPost is called. You need to override one (or both) of these methods to do what you want with the request and the response.
Read the javadoc of HttpServlet to learn more.
HttpServlet already define methods you can implement for different type of http request:
doGet()
doPost()
doDelete()
doPut()
etc...
All these methods have a request and response parameter.
You can read requested data, call any service you want, then write the response using the httpServletResponse from the parameter.
You don't have to define your own methods like you did in your question.
To anyone interested, here is an update code that does work by passing the ServletResponse to another class:
public void doPost(HttpServletRequest req, HttpServletResponse resp) {
try {
int len = req.getContentLength();
byte[] input = new byte[len];
ServletInputStream sin = req.getInputStream();
int c, count = 0 ;
while ((c = sin.read(input, count, input.length-count)) != -1) {
count +=c;
}
sin.close();
String inString = new String(input);
int index = inString.indexOf("=");
String value = inString.substring(index + 1);
inputStream = URLDecoder.decode(value, "UTF-8");
} catch (IOException e) {
}
responseWriter(resp);
}//end of requestReader
public void responseWriter(HttpServletResponse resp) {
try{
resp.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());
writer.write("Working");
writer.flush();
writer.close();
} catch (IOException e) {
}
}//end of responseWriter
This was all I was trying to achieve when I asked the question.