Skip to content
Snippets Groups Projects
Commit 92b90e97 authored by OZGCloud's avatar OZGCloud
Browse files

implement creating alfa notes

parent 5b6982a8
Branches
Tags
No related merge requests found
Showing
with 344 additions and 31 deletions
package de.ozgcloud.apilib.alfa;
import java.time.ZonedDateTime;
import java.util.Map;
import de.ozgcloud.apilib.common.command.OzgCloudCommand;
import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class CommandAlfaService implements AlfaService {
private final OzgCloudCommandService commandService;
@Override
public void addAktenNotiz(OzgCloudVorgangId vorgangId, String text) {
var command = createCreateItemCommand(vorgangId, text);
commandService.createAndWaitUntilDone(command);
}
OzgCloudCommand createCreateItemCommand(OzgCloudVorgangId vorgangId, String text) {
Map<String, Object> item = Map.of("text", text,
"createdAt", ZonedDateTime.now().toString());
Map<String, Object> commandBody = Map.of("item", item,
"vorgangId", vorgangId.toString(),
"itemName", "Kommentar",
"client", "Alfa");
return OzgCloudCommand.builder()
.order("CREATE_ATTACHED_ITEM")
.vorgangId(vorgangId)
.relationId(vorgangId)
.bodyObject(commandBody)
.build();
}
}
package de.ozgcloud.apilib.alfa.dummy;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import de.ozgcloud.apilib.alfa.AlfaService;
import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
import lombok.extern.java.Log;
@Log
@ConditionalOnMissingBean(OzgCloudVorgangService.class)
public class DummyAlfaService implements AlfaService {
@Override
......
package de.ozgcloud.apilib.common.command;
import java.util.Set;
import de.itvsh.kop.common.datatype.StringBasedValue;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class OzgCloudCommandStatus extends StringBasedValue {
public static final OzgCloudCommandStatus PENDING = from("PENDING");
public static final OzgCloudCommandStatus FINISHED = from("FINISHED");
public static final OzgCloudCommandStatus ERROR = from("ERROR");
public static final OzgCloudCommandStatus REVOKE_PENDING = from("REVOKE_PENDING");
public static final OzgCloudCommandStatus REVOKED = from("REVOKED");
public static final OzgCloudCommandStatus PENDING = new OzgCloudCommandStatus("PENDING");
public static final OzgCloudCommandStatus FINISHED = new OzgCloudCommandStatus("FINISHED");
public static final OzgCloudCommandStatus ERROR = new OzgCloudCommandStatus("ERROR");
public static final OzgCloudCommandStatus REVOKE_PENDING = new OzgCloudCommandStatus("REVOKE_PENDING");
public static final OzgCloudCommandStatus REVOKED = new OzgCloudCommandStatus("REVOKED");
private static final Set<OzgCloudCommandStatus> FINAL_STATES = Set.of(FINISHED, ERROR, REVOKED);
OzgCloudCommandStatus(String status) {
super(status);
......@@ -17,4 +23,8 @@ public class OzgCloudCommandStatus extends StringBasedValue {
public static OzgCloudCommandStatus from(String status) {
return new OzgCloudCommandStatus(status);
}
public boolean isFinalState() {
return FINAL_STATES.contains(this);
}
}
package de.ozgcloud.apilib.common.command.grpc;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import de.itvsh.kop.common.datatype.StringBasedValue;
import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
import de.ozgcloud.apilib.common.command.OzgCloudCommand;
import de.ozgcloud.apilib.common.command.OzgCloudCommandId;
import de.ozgcloud.apilib.common.command.OzgCloudCommandStatus;
import de.ozgcloud.apilib.common.datatypes.GenericId;
import de.ozgcloud.apilib.user.OzgCloudUserId;
import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId;
@Mapper(uses = { GrpcObjectMapper.class })
public interface CommandMapper {
@Mapping(target = "mergeFrom", ignore = true)
@Mapping(target = "clearField", ignore = true)
@Mapping(target = "clearOneof", ignore = true)
@Mapping(target = "mergeBodyObj", ignore = true)
@Mapping(target = "mergeCallContext", ignore = true)
@Mapping(target = "mergeRedirectRequest", ignore = true)
@Mapping(target = "mergeUnknownFields", ignore = true)
@Mapping(target = "removeBody", ignore = true)
@Mapping(target = "callContext", ignore = true)
@Mapping(target = "order", ignore = true)
@Mapping(target = "orderStringBytes", ignore = true)
@Mapping(target = "orderValue", ignore = true)
@Mapping(target = "redirectRequest", ignore = true)
@Mapping(target = "relationIdBytes", ignore = true)
@Mapping(target = "unknownFields", ignore = true)
@Mapping(target = "vorgangIdBytes", ignore = true)
@Mapping(target = "allFields", ignore = true)
@Mapping(target = "bodyBuilderList", ignore = true)
@Mapping(target = "bodyList", ignore = true)
@Mapping(target = "bodyOrBuilderList", ignore = true)
@Mapping(target = "bodyObj", source = "bodyObject")
@Mapping(target = "orderString", source = "order")
GrpcCreateCommandRequest buildCreateCommandRequest(OzgCloudCommand commandToCreate);
@Mapping(target = "bodyObject", source = "bodyObj")
@Mapping(target = "order", source = "orderString")
@Mapping(target = "relationVersion", ignore = true)
@Mapping(target = "relationId", qualifiedByName = "mapRelationId")
@Mapping(target = "body", ignore = true)
OzgCloudCommand fromGrpc(GrpcCommand command);
@Named("mapRelationId")
default StringBasedValue mapRelationId(String relationId) {
return GenericId.from(relationId);
}
default OzgCloudVorgangId toOzgCloudVorgangId(String userId) {
return OzgCloudVorgangId.from(userId);
}
default OzgCloudUserId toOzgCloudUserId(String userId) {
return OzgCloudUserId.from(userId);
}
default OzgCloudCommandStatus toOzgCloudCommandStatus(String status) {
return OzgCloudCommandStatus.from(status);
}
default OzgCloudCommandId toOzgCloudCommandId(String id) {
return OzgCloudCommandId.from(id);
}
default String valueToString(StringBasedValue value) {
return value.toString();
}
}
package de.ozgcloud.apilib.common.command.grpc;
import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
import de.ozgcloud.apilib.common.command.OzgCloudCommand;
import de.ozgcloud.apilib.common.command.OzgCloudCommandId;
import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.client.inject.GrpcClient;
......@@ -11,27 +11,41 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
@RequiredArgsConstructor
public class GrpcOzgCloudCommandService implements OzgCloudCommandService {
private static final int WAIT_TIME_MS = 500;
@GrpcClient("command-manager")
private final CommandServiceBlockingStub commandServiceStub;
private GrpcObjectMapper objectMapper;
private final CommandMapper mapper;
@Override
public OzgCloudCommand createAndWaitUntilDone(OzgCloudCommand commandToCreate) {
var command = create(commandToCreate);
// TODO Auto-generated method stub
return null;
return waitUntilDone(create(commandToCreate));
}
OzgCloudCommand create(OzgCloudCommand commandToCreate) {
commandServiceStub.createCommand(buildCreateCommandRequest(commandToCreate));
return null;
var created = commandServiceStub.createCommand(mapper.buildCreateCommandRequest(commandToCreate));
return mapper.fromGrpc(created.getCommand());
}
GrpcCreateCommandRequest buildCreateCommandRequest(OzgCloudCommand commandToCreate) {
return GrpcCreateCommandRequest.newBuilder()
.build();
OzgCloudCommand waitUntilDone(OzgCloudCommand commandToWaitFor) {
var command = commandToWaitFor;
// TODO timeout
while (!command.getStatus().isFinalState()) {
synchronized (this) {
try {
wait(WAIT_TIME_MS);
command = reloadCommand(command.getId());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
return command;
}
private OzgCloudCommand reloadCommand(OzgCloudCommandId commandId) {
GrpcGetCommandRequest request = GrpcGetCommandRequest.newBuilder().setId(commandId.toString()).build();
return mapper.fromGrpc(commandServiceStub.getCommand(request));
}
}
package de.ozgcloud.apilib.common.datatypes;
import de.itvsh.kop.common.datatype.StringBasedValue;
public class GenericId extends StringBasedValue {
GenericId(String id) {
super(id);
}
public static GenericId from(String id) {
return new GenericId(id);
}
}
package de.ozgcloud.apilib.common.command.grpc;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import org.mockito.InjectMocks;
class CommandMapperTest {
@InjectMocks
private CommandMapper mapper = Mappers.getMapper(CommandMapper.class);
@Nested
class TestBuildCreateCommandRequest {
@Test
void shouldBuildRequest() {
var request = mapper.buildCreateCommandRequest(OzgCloudCommandTestFactory.create());
assertThat(request).usingRecursiveComparison().isEqualTo(GrpcCreateCommandRequestTestFactory.create());
}
}
}
package de.ozgcloud.apilib.common.command.grpc;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
public class GrpcCommandResponseTestFactory {
public static final GrpcCommandResponse create() {
return createBuilder().build();
}
public static final GrpcCommandResponse.Builder createBuilder() {
return GrpcCommandResponse.newBuilder()
.setCommand(GrpcCommandTestFactory.create());
}
}
package de.ozgcloud.apilib.common.command.grpc;
import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
public class GrpcCommandTestFactory {
public static GrpcCommand create() {
return createBuilder().build();
}
public static GrpcCommand.Builder createBuilder() {
return GrpcCommand.newBuilder();
}
}
......@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
......@@ -21,38 +22,73 @@ class GrpcOzgCloudCommandServiceTest {
@Mock
private CommandServiceBlockingStub serviceStub;
@Mock
private CommandMapper mapper;
@Nested
class TestCreateAndWaitUntilDone {
private OzgCloudCommand command = OzgCloudCommandTestFactory.create();
@Test
void shouldCallCreate() {
OzgCloudCommand command = OzgCloudCommandTestFactory.create();
var created = OzgCloudCommandTestFactory.create();
doReturn(created).when(service).create(any());
service.createAndWaitUntilDone(command);
verify(service).create(command);
}
@Nested
class BuildCreateCommandRequest {
@Test
void shouldBuildCommand() {
var request = service.buildCreateCommandRequest(OzgCloudCommandTestFactory.create());
void shouldWaitUntilDone() {
var created = OzgCloudCommandTestFactory.create();
doReturn(created).when(service).create(any());
assertThat(request).usingRecursiveComparison().isEqualTo(GrpcCreateCommandRequestTestFactory.create());
}
service.createAndWaitUntilDone(command);
verify(service).waitUntilDone(created);
}
@Nested
class Create {
@BeforeEach
void init() {
when(serviceStub.createCommand(any())).thenReturn(GrpcCommandResponseTestFactory.create());
}
@Test
void shouldBuildRequest() {
service.create(command);
verify(mapper).buildCreateCommandRequest(command);
}
@Test
void shouldCallStub() {
var request = GrpcCreateCommandRequestTestFactory.create();
doReturn(request).when(service).buildCreateCommandRequest(any());
doReturn(request).when(mapper).buildCreateCommandRequest(any());
service.create(OzgCloudCommandTestFactory.create());
verify(serviceStub).createCommand(notNull());
verify(serviceStub).createCommand(request);
}
@Test
void shouldMapCommand() {
service.create(command);
verify(mapper).fromGrpc(GrpcCommandTestFactory.create());
}
@Test
void shouldReturnResult() {
var expected = OzgCloudCommandTestFactory.create();
when(mapper.fromGrpc(any())).thenReturn(expected);
var returned = service.create(command);
assertThat(returned).isSameAs(expected);
}
}
}
......
......@@ -13,7 +13,7 @@ import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
@Component
class DemoRunner implements ApplicationListener<ContextRefreshedEvent> {
private static final OzgCloudVorgangId VORGANG_ID = OzgCloudVorgangId.from("64dde1bd0ffe733638cc7d2a");
private static final OzgCloudVorgangId VORGANG_ID = OzgCloudVorgangId.from("64e889ba8e24a914a1628047");
@Autowired
private OzgCloudVorgangService vorgangService;
......
ozgcloud:
vorgang-manager:
# address: static://127.0.0.1:9090
address: nordfriesland-pluto-grpc.test.by.ozg-cloud.de:443
negotiation-type: tls
address: static://127.0.0.1:9090
# address: nordfriesland-pluto-grpc.test.by.ozg-cloud.de:443
negotiation-type: plaintext
file-manager:
address: ${ozgcloud.vorgang-manager.address}
negotiation-type: plaintext
command-manager:
address: ${ozgcloud.vorgang-manager.address}
negotiation-type: plaintext
\ No newline at end of file
......@@ -2,6 +2,7 @@ package de.ozgcloud.client.autoconfigure;
import java.util.Map;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
......@@ -11,11 +12,16 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
import de.ozgcloud.apilib.alfa.AlfaService;
import de.ozgcloud.apilib.alfa.CommandAlfaService;
import de.ozgcloud.apilib.alfa.dummy.DummyAlfaService;
import de.ozgcloud.apilib.common.callcontext.DefaultOzgCloudCallContextProvider;
import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextAttachingInterceptor;
import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
import de.ozgcloud.apilib.common.command.OzgCloudCommandService;
import de.ozgcloud.apilib.common.command.grpc.CommandMapper;
import de.ozgcloud.apilib.common.command.grpc.GrpcOzgCloudCommandService;
import de.ozgcloud.apilib.file.dummy.DummyOzgCloudFileService;
import de.ozgcloud.apilib.file.grpc.GrpcOzgCloudFileService;
import de.ozgcloud.apilib.vorgang.dummy.DummyVorgangService;
......@@ -23,6 +29,7 @@ import de.ozgcloud.apilib.vorgang.grpc.GrpcOzgCloudVorgangService;
import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
import net.devh.boot.grpc.client.config.GrpcChannelProperties;
import net.devh.boot.grpc.client.config.GrpcChannelsProperties;
import net.devh.boot.grpc.client.inject.GrpcClient;
@AutoConfiguration(before = GrpcClientAutoConfiguration.class)
@ComponentScan("de.ozgcloud.client.autoconfigure")
......@@ -35,11 +42,14 @@ public class OzgCloudClientAutoConfiguration {
private static final String CLIENT_NAME_VORGANG_MANAGER = "vorgang-manager";
private static final String CLIENT_NAME_FILE_MANAGER = "file-manager";
private static final String CLIENT_NAME_COMMAND_MANAGER = "command-manager";
@Autowired
private OzgCloudVorgangManagerProperties vorgangManagerProperties;
@Autowired
private OzgCloudFileManagerProperties fileManagerProperties;
@Autowired
private OzgCloudCommandManagerProperties commandManagerProperties;
@Bean
@ConditionalOnProperty("ozgcloud.vorgang-manager.address")
......@@ -49,6 +59,7 @@ public class OzgCloudClientAutoConfiguration {
addVorgangManager(clientMap);
addFileManager(clientMap);
addCommandManager(clientMap);
return properties;
}
......@@ -69,12 +80,39 @@ public class OzgCloudClientAutoConfiguration {
clientMap.put(CLIENT_NAME_FILE_MANAGER, channelProps);
}
private void addCommandManager(Map<String, GrpcChannelProperties> clientMap) {
var channelProps = new GrpcChannelProperties();
channelProps.setAddress(commandManagerProperties.getAddress());
channelProps.setNegotiationType(commandManagerProperties.getNegotiationType());
clientMap.put(CLIENT_NAME_COMMAND_MANAGER, channelProps);
}
@Bean
@ConditionalOnMissingBean
OzgCloudCallContextProvider callContextProvider(ApplicationContext ctxt) {
return new DefaultOzgCloudCallContextProvider(ctxt);
}
@Bean
@ConditionalOnProperty("ozgcloud.command-manager.address")
OzgCloudCommandService grpcCommandService(@GrpcClient("command-manager") CommandServiceBlockingStub commandServiceStub,
CommandMapper commandMapper) {
return new GrpcOzgCloudCommandService(commandServiceStub, commandMapper);
}
@Bean
@ConditionalOnProperty("ozgcloud.command-manager.address")
CommandMapper commandMapper() {
return Mappers.getMapper(CommandMapper.class);
}
@Bean
@ConditionalOnProperty("ozgcloud.command-manager.address")
AlfaService commandAlfaService(OzgCloudCommandService commandService) {
return new CommandAlfaService(commandService);
}
@Bean
@ConditionalOnMissingBean
AlfaService alfaService() {
......
package de.ozgcloud.client.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import lombok.Getter;
import lombok.Setter;
import net.devh.boot.grpc.client.config.NegotiationType;
@Getter
@Setter
@Configuration
@ConfigurationProperties("ozgcloud.command-manager")
public class OzgCloudCommandManagerProperties {
/**
* Network-Address of the Command-Manager instance, starting with resolving
* protocol. Example for local use: static://127.0.0.1:9090
*/
private String address;
/**
* Negotiation Type for the gRPC connection - possible Values: PLAINTEXT, TLS
*/
private NegotiationType negotiationType = NegotiationType.valueOf("TLS");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment