MockWebServer returning Json but restTemplate.exchange always maps to null - jackson

I am writing an integration test for a java component that calls some local service (in port 8888). I am able to intercept the call by passing the port as an argument to the MockWebServer, like this:
MockWebServer server= new MockWebServer();
server.start(8888);
server.enqueue(new MockResponse().setBody("{ \"score\": \"1.0\", \"match\": true, \"id\":\"faq.faq8\"}")
.addHeader("Content-Type", "application/json"));
Now the actual call is something like this:
ResponseEntity<Response> responseEntity = restTemplate.exchange(url.toUriString(), HttpMethod.POST,
requestEntity, Response.class);
And the response class looks like this:
public static class Response implements Serializable {
/* Serial UUID. */
private static final long serialVersionUID = -7548720302478842018L;
private boolean match;
private float score;
private String id;
public boolean isMatch() {
return match;
}
public float getScore() {
return score;
}
public String getId() {
return id;
}
}
I can make the response score and match fields to be whatever I want, but the id field is always null. I honestly have no idea why.

Related

How to receive a JSON File with multiple nodes through a POST Request with JAX-RS and Jackson (Quarkus)

When im tryin got do a Post request through my JAX-RS API it always sends a null value. I dont know if the Jackson annotations are incorrect or if i need to use an ObjectMapper.
These are my classes:
public class ClassA{
private String name;
private ClassB classB;
public ClassA(){}
public ClassA(String name, ClassB classB){
this.name = name;
this.classB = classB;
}
#JsonGetter
public String getName(){ return name; }
#JsonGetter
public ClassB getClassB(){ return classB; }
and this is the classB
public class ClassB{
#JsonProperty("type")
private String type;
#JsonProperty("number")
private int number;
public ClassB(){}
#JsonPropertyOrder({"type, number"})
public ClassB(String type, int number){
this.type= type;
this.number= number;
}
#JsonGetter
public String getType(){ return type; }
#JsonGetter
public int getNumber(){ return number; }
My JSON file:
{
"type": "typeExample;
"classB": {
"type": "classBTypeExample";
"int": 10;
}
}
I want Jackson to read the file and then add an Object type ClassA to a list (the problem is that is not even reading it)
This is the API code:
#Path("/path")
public class Requests {
private Set<ClassA> classesA = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
#GET
public Set<ClassA> list() {
return classesA;
}
#POST
public Set<ClassA> add(ClassA classA){
classesA.add(classA);
return classesA;
}
}
I already added the quarkus.jackson.fail-on-unknown-properties=true to the application.properies file
It was a simple thing that i didnt notice. I forgot to set the values on the constructer. So i just had to add the #ConstructorProperties({}) to the classes constructors and it worked out.

How to put a path param to the request body before validation happens?

I got the following test entity:
public class Test {
public String id;
public String name;
}
My test resource looks like this:
#Path("test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class TestResource {
#Path("{id}")
#POST
public Test test(#Valid Test test){
return test;
}
}
If I do a POST with name as request body, I will end up with an entity which has a name but no id set. If I want to have set the id, I define a #PathParam("id") String id and then set the id with test.id = id. That is what I am using right now.
In this case, if I put a #NotNull constraint to the ID, the validation fails.
How can I 'put' the parsed ID to the request body, before the validation is happening? Ideal, not manually in any case.
You should remove the #NotNull annotation and ensure that no ID is given from the POST request. And in your GET endpoints ensure that the field is not null, probably with an own annotation. I did this with my own annotation #TestIdNull(false).
In your code you would place the annotation like this:
#Path("{id}")
#POST
public Test test(#TestIdNull(true) Test test){
return test;
}
while the annotation interface looks quite simple:
#Target({ElementType.PARAMETER,ElementType.TYPE_USE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = PetIdNullValidator.class)
public #interface TestIdNull {
String message() default "Post request. ID value forbidden.";
boolean value() default true;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and the implementation would be
#Provider
#NoArgsConstructor
public class TestIdNullValidator implements ConstraintValidator<TestIdNull, Test> {
private boolean switchNullCheck;
/**
* {#inheritDoc}
*/
#Override
public void initialize(final TestIdNull constraintAnnotation) {
switchNullCheck = constraintAnnotation.value();
}
/**
* {#inheritDoc}
*/
#Override
public boolean isValid(final Test test, final ConstraintValidatorContext context) {
if (null == test) {
return true;
}
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("ENTER YOUR MESSAGE HERE").addConstraintViolation();
return switchNullCheck ? test.id() == null : test.id() != null;
}
}
On your "way back" (the GET methods) you must ensure the ID is not null with placing the annotation to your DTO. Code could look like this:
#TestIdNull(false)
final Test test = mapper.map(entity, Test.class);
I know it's not a very elegant way but your idea placing the ID in a POST first and then validate is not possible I'm afraid.

How to see arguments when creating a new class?

When creating a new class or method I used to be able to see the parameters needed. But, now they don't come up anymore. How do I view parameters when creating a class?
Running the latest windows version.
public class Main {
public static void main(String args[]) {
Case theCase = new Case("Default", "Corsair", "500W");
}
}
public class Case {
private String model;
private String manufacturer;
private String powerSupply;
public Case(String model, String manufacturer, String powerSupply,) {
this.model = model;
this.manufacturer = manufacturer;
this.powerSupply = powerSupply;
}
public void pressPowerButton() {
System.out.println("Power button pressed");
}
public String getModel() {
return model;
}
public String getManufacturer() {
return manufacturer;
}
public String getPowerSupply() {
return powerSupply;
}
}
When making theCase I can't see what my parameters are and have to move to the "Case" class back and forth
You can explicitly call Parameter Info action which is usually mapped to Ctrl/(Cmd) - p.
Nevermind in order to see the parameters as you type you must type them while in the editor without moving your cursor.

Jackson - Deserialize with JsonView

I am trying to restrict which properties from a JSON object are deserialised using Jackson JSONViews. The aim is to use this to prevent consumers of my API from submitting data that they shouldn't.
The problem is, I have either misunderstood JSONViews or I am doing something wrong. See below.
I started trying to do this in Spring but have noticed that even the simple test below doesn't work.
Account Class
public class Account {
#Id
private String id;
private String name;
private List<String> items;
private List<User> users;
#JsonView(AccountViews.Private.class)
public void setId(String id) {
this.id = id;
}
#JsonView(AccountViews.Public.class)
public void setName(String name) {
this.name = name;
}
#JsonView(AccountViews.Public.class)
public void setItems(List<String> items) {
this.items = items;
}
#JsonView(AccountViews.Private.class)
public void setUsers(List<User> users) {
this.users = users;
}
}
Views
public class AccountViews {
public interface Public {}
public interface Private extends Public {}
}
Test
#Test
public void testDeserialization(){
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
Account account = mapper.readerWithView(AccountViews.Public.class).forType(Account.class).readValue("{ \"name\": \"account1\", \"items\": [\"item1\"], \"users\": [ { \"firstname\": \"user1_firstname\", \"lastname\": \"user1_lastname\" }] }");
assertEquals(account.getName(), "account1");
assertNull(account.getUsers());
}
Unforunately, the 2nd assertion fails because Users has a user object inside.
Basically, even though "users" is a property of Account, I don't want the value to be deserialized because I have used the JSONView (AccountViews.Public.class). However, whatever I try it always seems to be deserialized and is present on the account object.
Any help much appreciated.
Error
`java.lang.AssertionError: expected null, but was:<[User#609db43b]>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotNull(Assert.java:755)
at org.junit.Assert.assertNull(Assert.java:737)
at org.junit.Assert.assertNull(Assert.java:747)
at`

How organize and test this code?

I have a conceptual doubt about how to organize and test code like the following, where a call to an auxiliary method is the first instruction of all the public methods of the class. My idea is make the code clean and testable.
The code is an example to try to illustrate this by a class "cache". This class has an optional prefix will be applied to all keys in the cache if it is set.
import java.util.HashMap;
public class Cache {
private HashMap<String, Integer> inMemoryCache;
private String prefix;
public Cache() {
this.inMemoryCache = new HashMap<String, Integer>();
prefix = null;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public int getValue(String key) throws NullPointerException {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.get(prefixedKey);
}
public void setValue(String key, int value) {
String prefixedKey = applyPrefixOrDefault(key);
inMemoryCache.put(prefixedKey, value);
}
public boolean isCached(String key) {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.containsKey(prefixedKey);
}
private String applyPrefixOrDefault(String key) {
if (prefix == null) {
return key;
} else {
return prefix + key;
}
}
public static void main (String[] arg) {
Cache cache = new Cache();
cache.setPrefix("global:");
cache.setValue("id", 4);
int value = cache.getValue("id");
System.out.println(value);
}
}
This code poses two questions to me:
If I had many methods accessing the inner hash table, would it be right separate the behavior of the cache in one class and the behavior of the prefix in other?
What would be the cleanest way to test this? Test the getValue, setValue and isCached is simple if we do not consider the prefix. With the prefix we need to test two things, the correct internal behavior of the cache and we need test also that all methods call applyPrefixOrDefault before accessing the data.
This is a common use case and I'm sure there must be some design pattern to organize this. Any idea?
To my opinion, what we miss here is a constructor that let us set the state of the cache. So I would add one as follows:
public Cache() {
this(null, new HashMap<String, Integer>());
}
public Cache(String prefix, Map<String, Integer> cache) {
this.prefix = prefix;
this.inMemoryCache = cache;
}
With this new constructor, you should be able to write test-cases for every possible cache state. I would also change the visibility of the applyPrefixOrDefault method to protected or package so that test code can access it. For instance, to test the GetValue method, I would write:
public class EmptyCacheTests {
private final Map<String, Integer> memory;
private final String prefix;
private final Cache cache;
public EmptyCacheTests() {
this.memory = new HasMap<String, Integer>();
this.prefix = "foo";
this.cache = new Cache(prefix, memory);
}
public void testGetValue() {
String key = this.cache.applyPrefixOrDefault("bar")
this.memory.put(key, 50);
result = this.cache.getValue("bar");
assertEquals(50, result, "The value retrieved is wrong!");
}
}
The point here, it to allow the test to set up the internal state of the cache, so that we can then test against many different ones.