CordaClient: use FlowResult
This commit is contained in:
		
							parent
							
								
									7df57cb4d2
								
							
						
					
					
						commit
						a9b70b963c
					
				| @ -14,17 +14,23 @@ import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.web.client.RestTemplate; | ||||
| 
 | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import com.fasterxml.jackson.databind.JsonMappingException; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| 
 | ||||
| import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; | ||||
| import djmil.cordacheckers.cordaclient.dao.Color; | ||||
| import djmil.cordacheckers.cordaclient.dao.GameProposal; | ||||
| import djmil.cordacheckers.cordaclient.dao.VirtualNode; | ||||
| import djmil.cordacheckers.cordaclient.dao.VirtualNodeList; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.RequestBody; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.ResponseBody; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.CreateGameProposal; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateReq; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateRes; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalListRes; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.Empty; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalAction; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionReq; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionRes; | ||||
| 
 | ||||
| @Service | ||||
| public class CordaClient { | ||||
| @ -59,7 +65,7 @@ public class CordaClient { | ||||
|      * @param holdingIdentity | ||||
|      * @return GameProposals list in JSON form | ||||
|      */ | ||||
|     public String listGameProposals(HoldingIdentity holdingIdentity) { | ||||
|     public List<GameProposal> gameProposalList(HoldingIdentity holdingIdentity) { | ||||
| 
 | ||||
|         final RequestBody requestBody = new RequestBody( | ||||
|             "list-" + UUID.randomUUID(), | ||||
| @ -67,21 +73,27 @@ public class CordaClient { | ||||
|             new Empty() | ||||
|             ); | ||||
| 
 | ||||
|         final String gameProposalsJsonString = cordaFlowExecute( | ||||
|         final GameProposalListRes listFlowResult = cordaFlowExecute( | ||||
|             holdingIdentity, | ||||
|             requestBody | ||||
|             requestBody, | ||||
|             GameProposalListRes.class | ||||
|             ); | ||||
| 
 | ||||
|         return gameProposalsJsonString; | ||||
|         if (listFlowResult.failureStatus() != null) { | ||||
|             System.out.println("GameProposalCreateFlow failed: " + listFlowResult.failureStatus()); | ||||
|             throw new RuntimeException("GameProsal: CreateFlow execution has failed"); | ||||
|         } | ||||
| 
 | ||||
|     public String createGameProposal( | ||||
|         return listFlowResult.successStatus(); | ||||
|     } | ||||
| 
 | ||||
|     public UUID gameProposalCreate( | ||||
|         HoldingIdentity sender, | ||||
|         HoldingIdentity receiver, | ||||
|         Color receiverColor, | ||||
|         String message | ||||
|     ) { | ||||
|         final CreateGameProposal createGameProposal = new CreateGameProposal( | ||||
|     ) throws JsonMappingException, JsonProcessingException { | ||||
|         final GameProposalCreateReq createGameProposal = new GameProposalCreateReq( | ||||
|             receiver.x500Name(), | ||||
|             receiverColor, | ||||
|             message | ||||
| @ -93,21 +105,28 @@ public class CordaClient { | ||||
|             createGameProposal | ||||
|             ); | ||||
| 
 | ||||
|         final String createdGameProposalUuid = cordaFlowExecute( | ||||
|         final GameProposalCreateRes createResult = cordaFlowExecute( | ||||
|             sender, | ||||
|             requestBody | ||||
|             requestBody, | ||||
|             GameProposalCreateRes.class | ||||
|             ); | ||||
| 
 | ||||
|         return createdGameProposalUuid; | ||||
|         if (createResult.failureStatus() != null) { | ||||
|             System.out.println("GameProposalCreateFlow failed: " + createResult.failureStatus()); | ||||
|             throw new RuntimeException("GameProsal: CreateFlow execution has failed"); | ||||
|         } | ||||
| 
 | ||||
|     public String rejectGameProposal( | ||||
|         return createResult.successStatus(); | ||||
|     } | ||||
| 
 | ||||
|     public String gameProposalAction( | ||||
|         HoldingIdentity self, | ||||
|         String gameProposalUuid | ||||
|         UUID gameProposalUuid, | ||||
|         GameProposalActionReq.Action action | ||||
|     ) { | ||||
|         final GameProposalAction rejectGameProposal = new GameProposalAction( | ||||
|             gameProposalUuid, | ||||
|             GameProposalAction.Action.REJECT | ||||
|         final GameProposalActionReq rejectGameProposal = new GameProposalActionReq( | ||||
|             gameProposalUuid.toString(), | ||||
|             action | ||||
|             ); | ||||
| 
 | ||||
|         final RequestBody requestBody = new RequestBody( | ||||
| @ -116,15 +135,21 @@ public class CordaClient { | ||||
|             rejectGameProposal | ||||
|             ); | ||||
| 
 | ||||
|         final String createdGameProposalUuid = cordaFlowExecute( | ||||
|         final GameProposalActionRes actionResult = cordaFlowExecute( | ||||
|             self, | ||||
|             requestBody | ||||
|             requestBody, | ||||
|             GameProposalActionRes.class | ||||
|             ); | ||||
| 
 | ||||
|         return createdGameProposalUuid; | ||||
|         if (actionResult.failureStatus() != null) { | ||||
|             System.out.println("GameProposalActionFlow failed: " + actionResult.failureStatus()); | ||||
|             throw new RuntimeException("GameProsal: ActionFlow execution has failed"); | ||||
|         } | ||||
| 
 | ||||
|     private String cordaFlowExecute(HoldingIdentity holdingIdentity, RequestBody requestBody) { | ||||
|         return actionResult.successStatus(); | ||||
|     } | ||||
| 
 | ||||
|     private <T> T cordaFlowExecute(HoldingIdentity holdingIdentity, RequestBody requestBody, Class<T> flowResultType) { | ||||
| 
 | ||||
|         try { | ||||
|             final String requestBodyJson = this.jsonMapper.writeValueAsString(requestBody); | ||||
| @ -134,15 +159,9 @@ public class CordaClient { | ||||
|                 requestBodyJson | ||||
|             ); | ||||
| 
 | ||||
|             final String flowExecutionResult = cordaFlowPoll(startedFlow); | ||||
|             final String flowResult = cordaFlowPoll(startedFlow); | ||||
| 
 | ||||
|             // NOTE: | ||||
|             // At this point, real production code, probably should convert data between CordaFlow | ||||
|             // abstarction into ReactApp abstraction. Instead, to limit boring json shuffling, all | ||||
|             // family of Corda.List flows were deliberatly designed to return frontend frendly JSONs. | ||||
|             // At the same time, all other Corda flows, simply return plain text string with | ||||
|             // operation result. | ||||
|             return flowExecutionResult; | ||||
|             return this.jsonMapper.readValue(flowResult, flowResultType); | ||||
|         }  | ||||
|         catch (Exception e) { | ||||
|             throw new RuntimeException("Unable to perform "+requestBody.flowClassName() | ||||
| @ -204,15 +223,16 @@ public class CordaClient { | ||||
|                 "CordaClient.cordaFlowPoll: empty getBody()" | ||||
|             ); | ||||
| 
 | ||||
|             if (responseBody.isFlowCompleted() && responseBody.flowResult() != null) { | ||||
|                 System.out.println("Completed "+responseBody.flowResult()); | ||||
|                 return responseBody.flowResult(); | ||||
|             } else | ||||
|             if (responseBody.flowError() != null) { | ||||
|                 return "Flow execution error: " +responseBody.flowError(); | ||||
|                 throw new RuntimeException("CordaClient.cordaFlowPoll: flow execution error: "  | ||||
|                                             +responseBody.flowError()); | ||||
|             } | ||||
| 
 | ||||
|             if (responseBody.isFlowCompleted() && responseBody.flowResult() != null) { | ||||
|                 return responseBody.flowResult(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return "CordaClient.cordaFlowPoll: retry limit"; | ||||
|         throw new RuntimeException ("CordaClient.cordaFlowPoll: retry limit"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| package djmil.cordacheckers.cordaclient.dao; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||||
| 
 | ||||
| @JsonDeserialize | ||||
| @ -8,6 +10,6 @@ public record GameProposal( | ||||
|     String recipient, | ||||
|     Color recipientColor, | ||||
|     String message, | ||||
|     String id) { | ||||
|     UUID id) { | ||||
|      | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| package djmil.cordacheckers.cordaclient.dao.flow.arguments; | ||||
| 
 | ||||
| public record GameProposalAction(String gameProposalUuid, Action action) { | ||||
| public record GameProposalActionReq(String gameProposalUuid, Action action) { | ||||
|     public enum Action { | ||||
|         ACCEPT, | ||||
|         REJECT, | ||||
| @ -0,0 +1,5 @@ | ||||
| package djmil.cordacheckers.cordaclient.dao.flow.arguments; | ||||
| 
 | ||||
| public record GameProposalActionRes(String successStatus, String failureStatus) { | ||||
|      | ||||
| } | ||||
| @ -2,6 +2,6 @@ package djmil.cordacheckers.cordaclient.dao.flow.arguments; | ||||
| 
 | ||||
| import djmil.cordacheckers.cordaclient.dao.Color; | ||||
| 
 | ||||
| public record CreateGameProposal(String opponentName, Color opponentColor, String message) { | ||||
| public record GameProposalCreateReq(String opponentName, Color opponentColor, String message) { | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package djmil.cordacheckers.cordaclient.dao.flow.arguments; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||||
| 
 | ||||
| @JsonSerialize | ||||
| public record GameProposalCreateRes(UUID successStatus, String failureStatus) { | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package djmil.cordacheckers.cordaclient.dao.flow.arguments; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import djmil.cordacheckers.cordaclient.dao.GameProposal; | ||||
| 
 | ||||
| public record GameProposalListRes(List<GameProposal> successStatus, String failureStatus) { | ||||
|      | ||||
| } | ||||
| @ -1,6 +1,8 @@ | ||||
| package djmil.cordacheckers.gameproposal; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| @ -9,9 +11,12 @@ import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.util.UriComponentsBuilder; | ||||
| 
 | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import com.fasterxml.jackson.databind.JsonMappingException; | ||||
| 
 | ||||
| import djmil.cordacheckers.cordaclient.CordaClient; | ||||
| import djmil.cordacheckers.cordaclient.dao.HoldingIdentity; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.CreateGameProposal; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCreateReq; | ||||
| import djmil.cordacheckers.cordaclient.dao.Color; | ||||
| import djmil.cordacheckers.cordaclient.dao.GameProposal; | ||||
| import djmil.cordacheckers.user.HoldingIdentityResolver; | ||||
| @ -36,9 +41,9 @@ public class GameProposalController { | ||||
|     public ResponseEntity<String> findAllUnconsumed( | ||||
|         @AuthenticationPrincipal User player | ||||
|     ) { | ||||
|         String gpList = cordaClient.listGameProposals(player.getHoldingIdentity()); | ||||
|         List<GameProposal> gpList = cordaClient.gameProposalList(player.getHoldingIdentity()); | ||||
| 
 | ||||
|         return ResponseEntity.ok(gpList); | ||||
|         return ResponseEntity.ok(gpList.toString()); | ||||
|     } | ||||
| 
 | ||||
|     // @PostMapping() | ||||
| @ -50,15 +55,16 @@ public class GameProposalController { | ||||
|     @PostMapping() | ||||
|     public ResponseEntity<Void> createGameProposal( | ||||
|         @AuthenticationPrincipal User sender, | ||||
|         @RequestBody CreateGameProposal gpRequest, | ||||
|         @RequestBody GameProposalCreateReq gpRequest, | ||||
|         UriComponentsBuilder ucb | ||||
|     ) { | ||||
|     ) throws JsonMappingException, JsonProcessingException { | ||||
|         final HoldingIdentity gpSender = sender.getHoldingIdentity(); | ||||
|         // TODO: throw execption with custom type | ||||
|         final HoldingIdentity gpReceiver = holdingIdentityResolver.getByUsername(gpRequest.opponentName()); | ||||
|         final Color gpReceiverColor = gpRequest.opponentColor(); | ||||
| 
 | ||||
|         String newGameProposalUuid = cordaClient.createGameProposal( | ||||
|         // TODO handle expectionns here | ||||
|         UUID newGameProposalUuid = cordaClient.gameProposalCreate( | ||||
|             gpSender, | ||||
|             gpReceiver, | ||||
|             gpReceiverColor, | ||||
|  | ||||
| @ -6,14 +6,19 @@ import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| 
 | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import com.fasterxml.jackson.databind.JsonMappingException; | ||||
| 
 | ||||
| import djmil.cordacheckers.cordaclient.dao.Color; | ||||
| import djmil.cordacheckers.cordaclient.dao.GameProposal; | ||||
| import djmil.cordacheckers.cordaclient.dao.VirtualNode; | ||||
| import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalActionReq.Action; | ||||
| import djmil.cordacheckers.user.HoldingIdentityResolver; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| import javax.naming.InvalidNameException; | ||||
| 
 | ||||
| @ -34,44 +39,45 @@ public class CordaClientTest { | ||||
| 
 | ||||
|     @Test | ||||
|     void testGameProposalList() throws JsonProcessingException { | ||||
|         String resp = cordaClient.listGameProposals( | ||||
|             holdingIdentityResolver.getByUsername("alice")); | ||||
|         List<GameProposal> gpList = cordaClient.gameProposalList( | ||||
|             holdingIdentityResolver.getByUsername("Alice")); | ||||
| 
 | ||||
|         System.out.println("testListGameProposals "+ resp); | ||||
|         System.out.println("testListGameProposals\n"+ gpList); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     void testGemeProposalCreate() { | ||||
|     void testGemeProposalCreate() throws JsonMappingException, JsonProcessingException { | ||||
|         final String gpSender = "alice"; | ||||
|         final String gpReceiver = "bob"; | ||||
|         final Color gpReceiverColor = Color.WHITE; | ||||
|         final String gpMessage = "GameProposal create test"; | ||||
| 
 | ||||
|         final String gpUuid = cordaClient.createGameProposal( | ||||
|         final UUID createdGpUuid = cordaClient.gameProposalCreate( | ||||
|             holdingIdentityResolver.getByUsername(gpSender), | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver), | ||||
|             gpReceiverColor, | ||||
|             gpMessage | ||||
|         ); | ||||
| 
 | ||||
|         String listResSender = cordaClient.listGameProposals( | ||||
|         List<GameProposal> gpListSender = cordaClient.gameProposalList( | ||||
|             holdingIdentityResolver.getByUsername(gpSender)); | ||||
| 
 | ||||
|         String listResReceiver = cordaClient.listGameProposals( | ||||
|         assertThat(findByUuid(gpListSender, createdGpUuid)).isNotNull(); | ||||
| 
 | ||||
|         List<GameProposal> gpListReceiver = cordaClient.gameProposalList( | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver)); | ||||
| 
 | ||||
|         assertThat(listResSender).contains(gpUuid); | ||||
|         assertThat(listResReceiver).contains(gpUuid); | ||||
|         assertThat(findByUuid(gpListReceiver, createdGpUuid)).isNotNull(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     void testGemeProposalReject() { | ||||
|     void testGemeProposalReject() throws JsonMappingException, JsonProcessingException { | ||||
|         final String gpSender = "alice"; | ||||
|         final String gpReceiver = "bob"; | ||||
|         final Color gpReceiverColor = Color.WHITE; | ||||
|         final String gpMessage = "GameProposal create test"; | ||||
|         final String gpMessage = "GameProposal REJECT test"; | ||||
| 
 | ||||
|         final String gpUuid = cordaClient.createGameProposal( | ||||
|         final UUID gpUuid = cordaClient.gameProposalCreate( | ||||
|             holdingIdentityResolver.getByUsername(gpSender), | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver), | ||||
|             gpReceiverColor, | ||||
| @ -80,20 +86,37 @@ public class CordaClientTest { | ||||
| 
 | ||||
|         System.out.println("Create GP UUID "+ gpUuid); | ||||
| 
 | ||||
|         String listResSender = cordaClient.listGameProposals( | ||||
|             holdingIdentityResolver.getByUsername(gpSender)); | ||||
|         assertThatThrownBy(() -> { | ||||
|             cordaClient.gameProposalAction( | ||||
|                 holdingIdentityResolver.getByUsername(gpSender), | ||||
|                 gpUuid, | ||||
|                 Action.REJECT); | ||||
|         }); | ||||
| 
 | ||||
|         String listResReceiver = cordaClient.listGameProposals( | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver)); | ||||
| 
 | ||||
|         assertThat(listResSender).contains(gpUuid); | ||||
|         assertThat(listResReceiver).contains(gpUuid); | ||||
| 
 | ||||
|         final String rejectRes = cordaClient.rejectGameProposal( | ||||
|         final String rejectRes = cordaClient.gameProposalAction( | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver), | ||||
|             "1ed70601-c79a-486d-b907-8537f317083a" | ||||
|             gpUuid, | ||||
|             Action.REJECT | ||||
|         ); | ||||
| 
 | ||||
|         assertThat(rejectRes).isEqualToIgnoringCase("REJECTED"); | ||||
| 
 | ||||
|         List<GameProposal> gpListSender = cordaClient.gameProposalList( | ||||
|             holdingIdentityResolver.getByUsername(gpSender)); | ||||
| 
 | ||||
|         assertThat(findByUuid(gpListSender, gpUuid)).isNull(); | ||||
| 
 | ||||
|         List<GameProposal> gpListReceiver = cordaClient.gameProposalList( | ||||
|             holdingIdentityResolver.getByUsername(gpReceiver)); | ||||
| 
 | ||||
|         assertThat(findByUuid(gpListReceiver, gpUuid)).isNull(); | ||||
|     } | ||||
| 
 | ||||
|     private GameProposal findByUuid(List<GameProposal> gpList, UUID uuid) { | ||||
|         for (GameProposal gameProposal : gpList) { | ||||
|             if (gameProposal.id().compareTo(uuid) == 0) | ||||
|                 return gameProposal; | ||||
|         }; | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user