Skip to content

Commit

Permalink
[incubator-kie-issues-1557] Marshalling POJO Input/output in user task
Browse files Browse the repository at this point in the history
  • Loading branch information
elguardian committed Oct 23, 2024
1 parent 8525f22 commit 3367181
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@

import java.util.Map;
import java.util.List;
import java.io.IOException;
import java.util.Collection;

import jakarta.inject.Inject;

import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
Expand Down Expand Up @@ -52,14 +55,59 @@

import org.kie.kogito.usertask.model.*;

import jakarta.inject.Inject;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator.Validity;
import com.fasterxml.jackson.databind.module.SimpleModule;

@Path("/usertasks/instance")
public class UserTasksResource {

@Inject
UserTaskService userTaskService;

ObjectMapper mapper;

@Inject
public UserTasksResource(ObjectMapper objectMapper) {
mapper = objectMapper.copy();
SimpleModule module = new SimpleModule();
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public JavaType handleMissingTypeId(DeserializationContext ctxt, JavaType baseType, TypeIdResolver idResolver, String failureMsg) throws IOException {
return baseType;
}
});
mapper.registerModule(module);

PolymorphicTypeValidator validator = new PolymorphicTypeValidator() {

@Override
public Validity validateBaseType(MapperConfig<?> config, JavaType baseType) {
return Validity.ALLOWED;
}

@Override
public Validity validateSubClassName(MapperConfig<?> config, JavaType baseType, String subClassName) throws JsonMappingException {
return Validity.ALLOWED;
}

@Override
public Validity validateSubType(MapperConfig<?> config, JavaType baseType, JavaType subType) throws JsonMappingException {
return Validity.ALLOWED;
}

};
mapper.activateDefaultTypingAsProperty(validator, DefaultTyping.NON_FINAL, "@type");
}

@GET
@Produces(MediaType.APPLICATION_JSON)
public List<UserTaskView> list(@QueryParam("user") String user, @QueryParam("group") List<String> groups) {
Expand Down Expand Up @@ -102,18 +150,20 @@ public UserTaskView setOutput(
@PathParam("taskId") String taskId,
@QueryParam("user") String user,
@QueryParam("group") List<String> groups,
Map<String, Object> data) {
String body) throws Exception {
Map<String, Object> data = mapper.readValue(body, Map.class);
return userTaskService.setOutputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(UserTaskInstanceNotFoundException::new);
}

@PUT
@Path("/{taskId}/inputs")
@Consumes(MediaType.APPLICATION_JSON)
public UserTaskView setOutput(@PathParam("id") String id,
public UserTaskView setInputs(
@PathParam("taskId") String taskId,
@QueryParam("user") String user,
@QueryParam("group") List<String> groups,
Map<String, Object> data) {
String body) throws Exception{
Map<String, Object> data = mapper.readValue(body, Map.class);
return userTaskService.setInputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(UserTaskInstanceNotFoundException::new);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.List;
import java.util.Map;
import java.io.IOException;
import java.util.Collection;

import org.jbpm.util.JsonSchemaUtil;
Expand Down Expand Up @@ -47,6 +48,19 @@
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.UriComponentsBuilder;

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator.Validity;
import com.fasterxml.jackson.databind.module.SimpleModule;

import org.springframework.beans.factory.annotation.Autowired;

import org.kie.kogito.usertask.model.*;
Expand All @@ -58,6 +72,42 @@ public class UserTasksResource {
@Autowired
UserTaskService userTaskService;

ObjectMapper mapper;

@Autowired
public UserTasksResource(ObjectMapper objectMapper) {
mapper = objectMapper.copy();
mapper = objectMapper.copy();
SimpleModule module = new SimpleModule();
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public JavaType handleMissingTypeId(DeserializationContext ctxt, JavaType baseType, TypeIdResolver idResolver, String failureMsg) throws IOException {
return baseType;
}
});
mapper.registerModule(module);

PolymorphicTypeValidator validator = new PolymorphicTypeValidator() {

@Override
public Validity validateBaseType(MapperConfig<?> config, JavaType baseType) {
return Validity.ALLOWED;
}

@Override
public Validity validateSubClassName(MapperConfig<?> config, JavaType baseType, String subClassName) throws JsonMappingException {
return Validity.ALLOWED;
}

@Override
public Validity validateSubType(MapperConfig<?> config, JavaType baseType, JavaType subType) throws JsonMappingException {
return Validity.ALLOWED;
}

};
mapper.activateDefaultTypingAsProperty(validator, DefaultTyping.NON_FINAL, "@type");
}

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public List<UserTaskView> list(@RequestParam("user") String user, @RequestParam("group") List<String> groups) {
return userTaskService.list(IdentityProviders.of(user, groups));
Expand All @@ -84,22 +134,24 @@ public Collection<UserTaskTransitionView> transition(
@RequestParam("group") List<String> groups) {
return userTaskService.allowedTransitions(taskId, IdentityProviders.of(user, groups));
}

@PutMapping("/{taskId}/outputs")
public UserTaskView setOutput(
@PathVariable("taskId") String taskId,
@RequestParam("user") String user,
@RequestParam("group") List<String> groups,
@RequestBody Map<String, Object> data) {
@RequestBody String body) throws Exception {
Map<String, Object> data = mapper.readValue(body, Map.class);
return userTaskService.setOutputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}

@PutMapping("/{taskId}/inputs")
public UserTaskView setOutput(@PathVariable("id") String id,
public UserTaskView setInputs(
@PathVariable("taskId") String taskId,
@RequestParam("user") String user,
@RequestParam("group") List<String> groups,
@RequestBody Map<String, Object> data) {
@RequestBody String body) throws Exception {
Map<String, Object> data = mapper.readValue(body, Map.class);
return userTaskService.setInputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
import org.kie.kogito.usertask.model.AttachmentInfo;
import org.kie.kogito.usertask.model.CommentInfo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

import io.quarkus.test.junit.QuarkusIntegrationTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
Expand All @@ -39,6 +43,7 @@
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchema;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;

@QuarkusIntegrationTest
Expand Down Expand Up @@ -105,6 +110,66 @@ void testJsonSchema() throws IOException {
}
}

@Test
public void testInputOutputsViaJsonTypeProperty() throws Exception {
Traveller traveller = new Traveller("pepe", "rubiales", "[email protected]", "Spanish", null);

given()
.contentType(ContentType.JSON)
.when()
.body(Collections.singletonMap("traveller", traveller))
.post("/approvals")
.then()
.statusCode(201)
.extract()
.path("id");

String taskId = given()
.contentType(ContentType.JSON)
.queryParam("user", "admin")
.queryParam("group", "managers")
.when()
.get("/usertasks/instance")
.then()
.statusCode(200)
.extract()
.path("[0].id");

traveller = new Traveller("pepe2", "rubiales2", "[email protected]", "Spanish2", null);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTypingAsProperty(BasicPolymorphicTypeValidator.builder().build(), DefaultTyping.NON_FINAL, "@type");
String jsonBody = mapper.writeValueAsString(Map.of("traveller", traveller));
given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("taskId", taskId)
.body(jsonBody)
.put("/usertasks/instance/{taskId}/inputs")
.then()
.log().body()
.statusCode(200)
.body("inputs.traveller.firstName", is(traveller.getFirstName()))
.body("inputs.traveller.lastName", is(traveller.getLastName()))
.body("inputs.traveller.email", is(traveller.getEmail()))
.body("inputs.traveller.nationality", is(traveller.getNationality()));

given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("taskId", taskId)
.body(jsonBody)
.put("/usertasks/instance/{taskId}/outputs")
.then()
.log().body()
.statusCode(200)
.body("outputs.traveller.firstName", is(traveller.getFirstName()))
.body("outputs.traveller.lastName", is(traveller.getLastName()))
.body("outputs.traveller.email", is(traveller.getEmail()))
.body("outputs.traveller.nationality", is(traveller.getNationality()));
}

@Test
void testSaveTask() {
Traveller traveller = new Traveller("pepe", "rubiales", "[email protected]", "Spanish");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

import io.restassured.http.ContentType;

import static io.restassured.RestAssured.given;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(SpringExtension.class)
Expand Down Expand Up @@ -111,6 +116,66 @@ void testJsonSchemaFiles() {
}
}

@Test
public void testInputOutputsViaJsonTypeProperty() throws Exception {
Traveller traveller = new Traveller("pepe", "rubiales", "[email protected]", "Spanish", null);

given()
.contentType(ContentType.JSON)
.when()
.body(Collections.singletonMap("traveller", traveller))
.post("/approvals")
.then()
.statusCode(201)
.extract()
.path("id");

String taskId = given()
.contentType(ContentType.JSON)
.queryParam("user", "admin")
.queryParam("group", "managers")
.when()
.get("/usertasks/instance")
.then()
.statusCode(200)
.extract()
.path("[0].id");

traveller = new Traveller("pepe2", "rubiales2", "[email protected]", "Spanish2", null);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTypingAsProperty(BasicPolymorphicTypeValidator.builder().build(), DefaultTyping.NON_FINAL, "@type");
String jsonBody = mapper.writeValueAsString(Map.of("traveller", traveller));
given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("taskId", taskId)
.body(jsonBody)
.put("/usertasks/instance/{taskId}/inputs")
.then()
.log().body()
.statusCode(200)
.body("inputs.traveller.firstName", is(traveller.getFirstName()))
.body("inputs.traveller.lastName", is(traveller.getLastName()))
.body("inputs.traveller.email", is(traveller.getEmail()))
.body("inputs.traveller.nationality", is(traveller.getNationality()));

given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("taskId", taskId)
.body(jsonBody)
.put("/usertasks/instance/{taskId}/outputs")
.then()
.log().body()
.statusCode(200)
.body("outputs.traveller.firstName", is(traveller.getFirstName()))
.body("outputs.traveller.lastName", is(traveller.getLastName()))
.body("outputs.traveller.email", is(traveller.getEmail()))
.body("outputs.traveller.nationality", is(traveller.getNationality()));
}

@Test
void testCommentAndAttachment() {
Traveller traveller = new Traveller("pepe", "rubiales", "[email protected]", "Spanish", null);
Expand Down Expand Up @@ -371,4 +436,5 @@ void testUpdateTaskInfo() {
assertThat(downTaskInfo.getInputParams()).isNotNull();
assertThat(downTaskInfo.getInputParams().get("traveller")).isNull();
}

}

0 comments on commit 3367181

Please sign in to comment.