diff --git a/pom.xml b/pom.xml
index 9dca9683a298a672846b0d6b38c97b1fbc77390d..60f25f39cab6e984a59bf9c0d7379076299e7a09 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- biz.nynja.search
+ biz.nynja.search.grpc
search-service
0.0.1-SNAPSHOT
jar
@@ -77,15 +77,31 @@
1.6.1
+
+ org.springframework.boot
+ spring-boot-starter-data-cassandra
+
+
+
+ com.datastax.cassandra
+ cassandra-driver-core
+
+
+ io.netty
+ netty-handler
+
+
+
+
com.google.guava
guava
21.0
-
+
libs-snapshot-local.biz.nynja.protos
- search-intracoldev
+ search-service-intracoldev
1.0-SNAPSHOT
@@ -95,6 +111,12 @@
+
+ com.googlecode.libphonenumber
+ libphonenumber
+ 8.9.12
+
+
com.fasterxml.jackson.core
jackson-databind
@@ -112,6 +134,15 @@
groovy-all
+
+ io.micrometer
+ micrometer-core
+
+
+
+ io.micrometer
+ micrometer-registry-prometheus
+
diff --git a/src/main/java/biz/nynja/search/configuration/SearchAccountConfig.java b/src/main/java/biz/nynja/search/configuration/SearchAccountConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9991771643c057a8245ce1eb1cf42253f6f28ec
--- /dev/null
+++ b/src/main/java/biz/nynja/search/configuration/SearchAccountConfig.java
@@ -0,0 +1,35 @@
+package biz.nynja.search.configuration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+@Configuration
+public class SearchAccountConfig {
+
+ private final String accountServiceAddress;
+ private final int accountServicePort;
+
+// @Autowired
+ public SearchAccountConfig(Environment env) {
+ this.accountServiceAddress = env.getRequiredProperty("services.account.address");
+ this.accountServicePort = parseProperty(env, "services.account.port");
+ }
+
+ private int parseProperty(Environment env, String property) throws InternalError {
+ try {
+ return Integer.parseInt(env.getRequiredProperty(property));
+ } catch (NumberFormatException ex) {
+ throw new InternalError("Integer expected in " + property);
+ }
+ }
+
+ public String getAccountServiceAddress() {
+ return accountServiceAddress;
+ }
+
+ public int getAccountServicePort() {
+ return accountServicePort;
+ }
+
+}
diff --git a/src/main/java/biz/nynja/search/healthindicators/GrpcServerHealthIndicator.java b/src/main/java/biz/nynja/search/healthindicators/GrpcServerHealthIndicator.java
index cb98dd5c38d694013dbe713904bfd28982841940..3e0c604377fed4598d2b5ab4ee24e45b5d0912af 100644
--- a/src/main/java/biz/nynja/search/healthindicators/GrpcServerHealthIndicator.java
+++ b/src/main/java/biz/nynja/search/healthindicators/GrpcServerHealthIndicator.java
@@ -13,8 +13,8 @@ import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
-import biz.nynja.search.grpc.AccountServiceGrpc;
-import biz.nynja.search.services.AccountServiceImpl;
+import biz.nynja.search.grpc.SearchServiceGrpc;
+import biz.nynja.search.services.SearchServiceImpl;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.health.v1.HealthCheckRequest;
@@ -27,7 +27,7 @@ import io.grpc.health.v1.HealthGrpc;
@Component
public class GrpcServerHealthIndicator implements HealthIndicator {
- private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(SearchServiceImpl.class);
@Autowired
protected GRpcServerProperties gRpcServerProperties;
@@ -37,14 +37,14 @@ public class GrpcServerHealthIndicator implements HealthIndicator {
ManagedChannel channel = onChannelBuild(
ManagedChannelBuilder.forAddress("localhost", gRpcServerProperties.getPort()).usePlaintext()).build();
final HealthCheckRequest healthCheckRequest = HealthCheckRequest.newBuilder()
- .setService(AccountServiceGrpc.getServiceDescriptor().getName()).build();
+ .setService(SearchServiceGrpc.getServiceDescriptor().getName()).build();
final HealthGrpc.HealthFutureStub healthFutureStub = HealthGrpc.newFutureStub(channel);
HealthCheckResponse.ServingStatus servingStatus = null;
try {
servingStatus = healthFutureStub.check(healthCheckRequest).get().getStatus();
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Error retrieving health status for {}: {}",
- AccountServiceGrpc.getServiceDescriptor().getName(), e.getMessage());
+ SearchServiceGrpc.getServiceDescriptor().getName(), e.getMessage());
LOGGER.debug(null, e.getCause());
return Health.down().build();
}
diff --git a/src/main/java/biz/nynja/search/models/AccountInfo.java b/src/main/java/biz/nynja/search/models/AccountInfo.java
deleted file mode 100644
index 817cba1fb8af17a83a30bebc182306cdd8999b2d..0000000000000000000000000000000000000000
--- a/src/main/java/biz/nynja/search/models/AccountInfo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (C) 2018 Nynja Inc. All rights reserved.
- */
-package biz.nynja.search.models;
-
-import org.springframework.data.cassandra.core.mapping.PrimaryKey;
-import org.springframework.data.cassandra.core.mapping.Table;
-
-import biz.nynja.search.grpc.RegisterRequest;
-
-/**
- * Account bean as represented in the corresponding Cassandra table.
- */
-@Table
-public class AccountInfo {
-
- @PrimaryKey
- private Long id;
- private String email;
- private String password;
-
- public AccountInfo() {
- }
-
- public AccountInfo(long id, String email, String password) {
- this.id = id;
- this.email = email;
- this.password = password;
- }
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- @Override
- public String toString() {
- return "AccountInfo [id=" + id + ", email=" + email + ", password=" + password + "]";
- }
-
- public static AccountInfo fromProto(RegisterRequest proto) {
- AccountInfo accountInfo = new AccountInfo();
- accountInfo.setId(proto.getId());
- accountInfo.setEmail(proto.getEmail());
- accountInfo.setPassword(proto.getPassword());
- return accountInfo;
- }
-
- public biz.nynja.blueprint.grpc.AccountInfo toProto() {
- return biz.nynja.blueprint.grpc.AccountInfo.newBuilder().setId(Long.toString(getId())).setEmail(getEmail())
- .build();
- }
-}
diff --git a/src/main/java/biz/nynja/search/repositories/AccountInfoRepository.java b/src/main/java/biz/nynja/search/repositories/AccountInfoRepository.java
deleted file mode 100644
index bce17d84fd0e47f4c845bd6dd7f32d028c6036ed..0000000000000000000000000000000000000000
--- a/src/main/java/biz/nynja/search/repositories/AccountInfoRepository.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Copyright (C) 2018 Nynja Inc. All rights reserved.
- */
-package biz.nynja.search.repositories;
-
-import org.springframework.data.cassandra.repository.Query;
-import org.springframework.data.repository.CrudRepository;
-
-import biz.nynja.search.models.AccountInfo;
-
-/**
- * Account repository for Cassandra operations/queries.
- */
-public interface AccountInfoRepository extends CrudRepository {
-
- @Query(value = "SELECT * FROM AccountInfo WHERE email=?0 ALLOW FILTERING")
- public AccountInfo findByEmail(String email);
-}
diff --git a/src/main/java/biz/nynja/search/services/AccountServiceCommunicator.java b/src/main/java/biz/nynja/search/services/AccountServiceCommunicator.java
new file mode 100644
index 0000000000000000000000000000000000000000..41185578465f27e5ac1c1a437e106d96279f7553
--- /dev/null
+++ b/src/main/java/biz/nynja/search/services/AccountServiceCommunicator.java
@@ -0,0 +1,79 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.search.services;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import biz.nynja.search.grpc.SearchServiceGrpc;
+import biz.nynja.search.configuration.SearchAccountConfig;
+import biz.nynja.search.grpc.SearchByEmailRequest;
+import biz.nynja.search.grpc.SearchByPhoneNumberRequest;
+import biz.nynja.search.grpc.SearchByQrCodeRequest;
+import biz.nynja.search.grpc.SearchByUsernameRequest;
+import biz.nynja.search.grpc.SearchResponse;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+
+@Service
+public class AccountServiceCommunicator {
+
+ @Autowired
+ private SearchAccountConfig searchAccountConfig;
+
+ public SearchResponse searchByUsername(String username) {
+ SearchByUsernameRequest request = SearchByUsernameRequest.newBuilder().setUsername(username).build();
+
+ ManagedChannel managedChannel = ManagedChannelBuilder.forAddress(searchAccountConfig.getAccountServiceAddress(), searchAccountConfig.getAccountServicePort())
+ .usePlaintext().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(managedChannel);
+
+ SearchResponse response = searchServiceBlockingStub.searchByUsername(request);
+ return response;
+ }
+
+ public SearchResponse searchByPhoneNumber(String phoneNumber) {
+ SearchByPhoneNumberRequest request = SearchByPhoneNumberRequest.newBuilder().setPhoneNumber(phoneNumber)
+ .build();
+
+ ManagedChannel managedChannel = ManagedChannelBuilder.forAddress(searchAccountConfig.getAccountServiceAddress(), searchAccountConfig.getAccountServicePort())
+ .usePlaintext().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(managedChannel);
+
+ SearchResponse response = searchServiceBlockingStub.searchByPhoneNumber(request);
+ return response;
+ }
+
+ public SearchResponse searchByEmail(String email) {
+ SearchByEmailRequest request = SearchByEmailRequest.newBuilder().setEmail(email).build();
+
+ ManagedChannel managedChannel = ManagedChannelBuilder.forAddress(searchAccountConfig.getAccountServiceAddress(), searchAccountConfig.getAccountServicePort())
+ .usePlaintext().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(managedChannel);
+
+ SearchResponse response = searchServiceBlockingStub.searchByEmail(request);
+ return response;
+ }
+
+ public SearchResponse searchByQrCode(String qrcode) {
+ SearchByQrCodeRequest request = SearchByQrCodeRequest.newBuilder().setQrCode(qrcode).build();
+
+ ManagedChannel managedChannel = ManagedChannelBuilder.forAddress(searchAccountConfig.getAccountServiceAddress(), searchAccountConfig.getAccountServicePort())
+ .usePlaintext().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(managedChannel);
+
+ SearchResponse response = searchServiceBlockingStub.searchByQrCode(request);
+ return response;
+ }
+
+}
diff --git a/src/main/java/biz/nynja/search/services/AccountServiceImpl.java b/src/main/java/biz/nynja/search/services/AccountServiceImpl.java
deleted file mode 100644
index 665ee36242d20267a5e2441f83dbc4cd5a17262e..0000000000000000000000000000000000000000
--- a/src/main/java/biz/nynja/search/services/AccountServiceImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (C) 2018 Nynja Inc. All rights reserved.
- */
-package biz.nynja.search.services;
-
-import org.lognet.springboot.grpc.GRpcService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import biz.nynja.search.grpc.AccountServiceGrpc;
-import biz.nynja.search.grpc.RegisterError;
-import biz.nynja.search.grpc.RegisterRequest;
-import biz.nynja.search.grpc.RegisterResponse;
-import biz.nynja.search.grpc.RegisterError.Cause;
-import biz.nynja.search.models.AccountInfo;
-import biz.nynja.search.repositories.AccountInfoRepository;
-import io.grpc.stub.StreamObserver;
-
-/**
- * gRPC Account service implementation.
- * The service extends the protobuf generated class and overrides the needed methods. It also saves/retrieves the
- * account information via {@link AccountInfoRepository}.
- */
-@GRpcService
-public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBase {
-
- private static final Logger logger = LoggerFactory.getLogger(AccountServiceImpl.class);
-
- @Autowired
- private AccountInfoRepository accountInfoRepository;
-
- @Override
- public void register(RegisterRequest request, StreamObserver responseObserver) {
-
- logger.info("Got a gRPC service request: {}", request);
-
- AccountInfo accountInfo = AccountInfo.fromProto(request);
-
- if (accountInfoRepository.findByEmail(accountInfo.getEmail()) != null) {
- responseObserver.onNext(RegisterResponse.newBuilder()
- .setError(RegisterError.newBuilder().setCause(Cause.EMAIL_ALREADY_USED)).build());
- responseObserver.onCompleted();
- return;
- }
-
- AccountInfo savedAccount = accountInfoRepository.save(accountInfo);
- logger.info("Account \"{}\" saved into the DB", savedAccount.toString());
-
- RegisterResponse response = RegisterResponse.newBuilder().setAccount(savedAccount.toProto()).build();
- logger.info("Response from gRPC service: \"{}\"", response);
-
- responseObserver.onNext(response);
- responseObserver.onCompleted();
- }
-}
diff --git a/src/main/java/biz/nynja/search/services/SearchServiceImpl.java b/src/main/java/biz/nynja/search/services/SearchServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0c67cf324db6a3ac3149e87065b41d2d6ccae19
--- /dev/null
+++ b/src/main/java/biz/nynja/search/services/SearchServiceImpl.java
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.search.services;
+
+import org.lognet.springboot.grpc.GRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import biz.nynja.search.grpc.SearchServiceGrpc;
+import biz.nynja.search.grpc.ErrorResponse;
+import biz.nynja.search.grpc.ErrorResponse.Cause;
+import biz.nynja.search.grpc.SearchByEmailRequest;
+import biz.nynja.search.grpc.SearchByPhoneNumberRequest;
+import biz.nynja.search.grpc.SearchByQrCodeRequest;
+import biz.nynja.search.grpc.SearchByUsernameRequest;
+import biz.nynja.search.grpc.SearchResponse;
+import io.grpc.stub.StreamObserver;
+
+/**
+ * gRPC Search service implementation.
+ * The service extends the protobuf generated class and overrides the needed methods.
+ * It also saves/retrieves the account information via the Account service.
+ */
+@GRpcService
+public class SearchServiceImpl extends SearchServiceGrpc.SearchServiceImplBase {
+
+ private static final Logger logger = LoggerFactory.getLogger(SearchServiceImpl.class);
+
+ @Autowired
+ private AccountServiceCommunicator accountService;
+
+ @Override
+ public void searchByUsername(SearchByUsernameRequest request, StreamObserver responseObserver) {
+
+ logger.info("Searching account by username {}", request.getUsername());
+ if ((request.getUsername() == null) || request.getUsername().isEmpty()) {
+ logAndBuildGrpcResponse(responseObserver, "Missing username: {}", Cause.MISSING_USERNAME);
+ return;
+ }
+
+ SearchResponse response = accountService.searchByUsername(request.getUsername());
+
+ if ((response.getError() != null) && (response.getError().getCauseValue() != 0)) {
+ logAndBuildGrpcResponse(responseObserver, "Account service returns an error with the cause: {}", response.getError().getCause());
+ return;
+ }
+
+ logger.debug("Found result for search by username {}: \"{}\"", request.getUsername(), response);
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ return;
+ }
+
+ @Override
+ public void searchByPhoneNumber(SearchByPhoneNumberRequest request,
+ StreamObserver responseObserver) {
+
+ logger.info("Searching account by phone number {}", request.getPhoneNumber());
+ if ((request.getPhoneNumber() == null) || request.getPhoneNumber().isEmpty()) {
+ logAndBuildGrpcResponse(responseObserver, "Missing phone number: {}", Cause.MISSING_PHONENUMBER);
+ return;
+ }
+
+ SearchResponse response = accountService.searchByPhoneNumber(request.getPhoneNumber());
+
+ if (response.getError().getCauseValue() != 0) {
+ logAndBuildGrpcResponse(responseObserver, "Account service returns an error with the cause: {}", response.getError().getCause());
+ return;
+ }
+
+ logger.debug("Found result for search by phone number {}: \"{}\"", request.getPhoneNumber(), response);
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ return;
+ }
+
+ @Override
+ public void searchByEmail(SearchByEmailRequest request, StreamObserver responseObserver) {
+
+ logger.info("Searching account by e-mail {}", request.getEmail());
+ if ((request.getEmail() == null) || request.getEmail().isEmpty()) {
+ logAndBuildGrpcResponse(responseObserver, "Missing e-mail: {}", Cause.MISSING_EMAIL);
+ return;
+ }
+
+ SearchResponse response = accountService.searchByEmail(request.getEmail());
+
+ if (response.getError().getCauseValue() != 0) {
+ logAndBuildGrpcResponse(responseObserver, "Account service returns an error with the cause: {}", response.getError().getCause());
+ return;
+ }
+
+ logger.debug("Found result for search by phone number {}: \"{}\"", request.getEmail(), response);
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ return;
+ }
+
+ @Override
+ public void searchByQrCode(SearchByQrCodeRequest request, StreamObserver responseObserver) {
+
+ logger.info("Searching account by QR code {}", request.getQrCode());
+ if ((request.getQrCode() == null) || request.getQrCode().isEmpty()) {
+ logAndBuildGrpcResponse(responseObserver, "Missing QR code: {}", Cause.MISSING_QR_CODE);
+ return;
+ }
+
+ SearchResponse response = accountService.searchByQrCode(request.getQrCode());
+
+ if (response.getError().getCauseValue() != 0) {
+ logAndBuildGrpcResponse(responseObserver, "Account service returns an error with the cause: {}", response.getError().getCause());
+ return;
+ }
+
+ logger.debug("Found result for search by phone number {}: \"{}\"", request.getQrCode(), response);
+ responseObserver.onNext(response);
+ responseObserver.onCompleted();
+ return;
+ }
+
+ private static void logAndBuildGrpcResponse(StreamObserver responseObserver, String logMessage, Cause cause) {
+ logger.debug(logMessage, cause.toString());
+ responseObserver.onNext(SearchResponse.newBuilder()
+ .setError(ErrorResponse.newBuilder().setCause(cause)).build());
+ responseObserver.onCompleted();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index d33d2617d00f9e3406846346ee35e50eaa6ef94d..b8525f8032d65d055c0f7ab26c53f5b0c6af5ded 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -1,7 +1,17 @@
grpc:
enabled: true
enableReflection: false
- port: 6568
-
+ port: 6567
+ unitTest:
+ port:
+ searchServiceTest: 10002
+
+
+services:
+ account:
+ address: 127.0.0.1
+ port: 6565
+
server:
- port: 8084
\ No newline at end of file
+ port: 8018
+
diff --git a/src/main/resources/application-production.yml b/src/main/resources/application-production.yml
deleted file mode 100644
index 6280131fe1751248d5ef556573d7b45486d457e5..0000000000000000000000000000000000000000
--- a/src/main/resources/application-production.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-grpc:
- enabled: ${GRPC_ENABLED:true}
- enableReflection: ${GRPC_ENABLE_REFLECTION:false}
- port: ${GRPC_SERVER_PORT:6568}
-
-server:
- port: ${APPLICATION_SERVER_PORT:8084}
\ No newline at end of file
diff --git a/src/main/resources/logback-spring.groovy b/src/main/resources/logback-spring.groovy
index 82f9fa7c51bf4b0a5ecfca69fca4c716782c658c..5c01a5bf2229222617492a3768a9eb3e9e6dc2c6 100644
--- a/src/main/resources/logback-spring.groovy
+++ b/src/main/resources/logback-spring.groovy
@@ -3,6 +3,7 @@
*/
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
+import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.rolling.RollingFileAppender
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP
@@ -11,7 +12,7 @@ import ch.qos.logback.classic.Level
statusListener(OnConsoleStatusListener)
-def file = "${System.getProperty('log.dir', '')}blueprint-java-spring-service-%d.%i.log"
+def file = "${System.getProperty('log.dir', '')}search-service-%d.%i.log"
appender("FILE", RollingFileAppender) {
// add a status message regarding the file property
@@ -23,6 +24,10 @@ appender("FILE", RollingFileAppender) {
timeBasedFileNamingAndTriggeringPolicy(SizeAndTimeBasedFNATP) { maxFileSize = "10mb" }}
}
-logger("org.springframework.cloud.config.client.ConfigServicePropertySourceLocator", Level.WARN)
+appender("Console-Appender", ConsoleAppender) {
+ encoder(PatternLayoutEncoder) { pattern = "%d{HH:mm:ss.SSS} %level %logger - %msg%n" }
+}
+logger("org.springframework.cloud.config.client.ConfigServicePropertySourceLocator", Level.WARN)
+root(INFO, ["Console-Appender"])
root(Level.toLevel("${System.getProperty('log.level', 'INFO')}"), ["FILE"])
\ No newline at end of file
diff --git a/src/test/java/biz/nynja/search/ApplicationTests.java b/src/test/java/biz/nynja/search/ApplicationTests.java
index 9ae2bf56333393d9644a88b82a827d99b6941a1b..8ad63677b81957dfe2fec5a7850541cf70fd3e2a 100644
--- a/src/test/java/biz/nynja/search/ApplicationTests.java
+++ b/src/test/java/biz/nynja/search/ApplicationTests.java
@@ -3,6 +3,14 @@
*/
package biz.nynja.search;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.BDDMockito.given;
+
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -11,65 +19,294 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
-import biz.nynja.search.models.AccountInfo;
-import biz.nynja.search.repositories.AccountInfoRepository;
+import biz.nynja.search.grpc.ErrorResponse.Cause;
+import biz.nynja.search.grpc.ErrorResponse;
+import biz.nynja.search.grpc.SearchByEmailRequest;
+import biz.nynja.search.grpc.SearchByPhoneNumberRequest;
+import biz.nynja.search.grpc.SearchByQrCodeRequest;
+import biz.nynja.search.grpc.SearchByUsernameRequest;
+import biz.nynja.search.grpc.SearchResponse;
+import biz.nynja.search.grpc.SearchServiceGrpc;
+import biz.nynja.search.services.AccountServiceCommunicator;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Util.class,
- properties = {
+ properties = { "grpc.port=${grpc.unitTest.port.searchServiceTest}",
"spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration",
"spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration" })
@ActiveProfiles("dev")
public class ApplicationTests extends GrpcServerTestBase {
- @MockBean
- private AccountInfoRepository accountInfoRepository;
-
- @Autowired
- @Qualifier("newAccount")
- private AccountInfo accountInfo;
-
- @Autowired
- @Qualifier("savedAccount")
- private AccountInfo savedAccount;
- //
- // @Test
- // public void testRegister() throws ExecutionException, InterruptedException {
- //
- // String testEmail = "email@test.com";
- // final RegisterRequest request = RegisterRequest.newBuilder().setId(1).setEmail(testEmail).setPassword("abc")
- // .build();
- //
- // given(accountInfoRepository.findByEmail(testEmail)).willReturn(null);
- // given(accountInfoRepository.save(any(AccountInfo.class))).willReturn(savedAccount);
- //
- // final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- // .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
- //
- // final RegisterResponse reply = accountServiceBlockingStub.register(request);
- //
- // assertNotNull("Reply should not be null", reply);
- // assertTrue(String.format("Reply should contain email '%s'", testEmail),
- // reply.getAccount().getEmail().equals(testEmail));
- // }
- //
- // @Test
- // public void testRegisterExistEmail() throws ExecutionException, InterruptedException {
- //
- // String testEmail = "email@test.com";
- // final RegisterRequest request = RegisterRequest.newBuilder().setId(1).setEmail(testEmail).setPassword("abc")
- // .build();
- //
- // given(accountInfoRepository.findByEmail(testEmail)).willReturn(accountInfo);
- //
- // final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- // .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
- //
- // final RegisterResponse reply = accountServiceBlockingStub.register(request);
- //
- // assertNotNull("Reply should not be null", reply);
- // assertTrue(String.format("Reply should contain cause '%s'", testEmail),
- // reply.getError().getCause().equals(RegisterError.Cause.EMAIL_ALREADY_USED));
- // }
+ @MockBean
+ private AccountServiceCommunicator accountService;
+
+ @Autowired
+ @Qualifier("savedResponse")
+ private SearchResponse savedResponse;
+
+ @Test
+ public void testSearchByUsername() throws ExecutionException, InterruptedException {
+ final SearchByUsernameRequest request = SearchByUsernameRequest.newBuilder()
+ .setUsername(Util.USERNAME).build();
+
+ SearchResponse response = savedResponse;
+
+ given(accountService.searchByUsername(request.getUsername())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByUsername(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain last name '%s'", Util.LAST_NAME.toString()),
+ reply.getSearchResultDetails().getLastName().equals(Util.LAST_NAME.toString()));
+ }
+
+ @Test
+ public void testSearchByUsernameNotFound() throws ExecutionException, InterruptedException {
+ final SearchByUsernameRequest request = SearchByUsernameRequest.newBuilder()
+ .setUsername(Util.USERNAME).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.USERNAME_NOT_FOUND))).build();
+
+ given(accountService.searchByUsername(request.getUsername())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByUsername(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", biz.nynja.search.grpc.ErrorResponse.Cause.USERNAME_NOT_FOUND),
+ reply.getError().getCause().equals(biz.nynja.search.grpc.ErrorResponse.Cause.USERNAME_NOT_FOUND));
+ }
+
+ @Test
+ public void testSearchByUsernameBadRequest() throws ExecutionException, InterruptedException {
+ final SearchByUsernameRequest request = SearchByUsernameRequest.newBuilder().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByUsername(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.MISSING_USERNAME),
+ reply.getError().getCause().equals(Cause.MISSING_USERNAME));
+ }
+
+ @Test
+ public void testSearchByUsernameInvalid() {
+ final SearchByUsernameRequest request = SearchByUsernameRequest.newBuilder()
+ .setUsername(Util.INVALID_USERNAME).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.INVALID_USERNAME))).build();
+
+ given(accountService.searchByUsername(request.getUsername())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByUsername(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.INVALID_USERNAME),
+ reply.getError().getCause().equals(Cause.INVALID_USERNAME));
+ }
+
+ @Test
+ public void testSearchByPhoneNumber() throws ExecutionException, InterruptedException {
+ final SearchByPhoneNumberRequest request = SearchByPhoneNumberRequest.newBuilder()
+ .setPhoneNumber(Util.PHONE_NUMBER).build();
+
+ SearchResponse response = savedResponse;
+
+ given(accountService.searchByPhoneNumber(request.getPhoneNumber())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain last name '%s'", Util.LAST_NAME.toString()),
+ reply.getSearchResultDetails().getLastName().equals(Util.LAST_NAME.toString()));
+ }
+
+ @Test
+ public void testSearchByPhoneNumberNotFound() throws ExecutionException, InterruptedException {
+ final SearchByPhoneNumberRequest request = SearchByPhoneNumberRequest.newBuilder()
+ .setPhoneNumber(Util.PHONE_NUMBER).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.PHONENUMBER_NOT_FOUND))).build();
+
+ given(accountService.searchByPhoneNumber(request.getPhoneNumber())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", biz.nynja.search.grpc.ErrorResponse.Cause.PHONENUMBER_NOT_FOUND),
+ reply.getError().getCause().equals(biz.nynja.search.grpc.ErrorResponse.Cause.PHONENUMBER_NOT_FOUND));
+ }
+
+ @Test
+ public void testSearchByPhoneNumberBadRequest() throws ExecutionException, InterruptedException {
+ final SearchByPhoneNumberRequest request = SearchByPhoneNumberRequest.newBuilder().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.MISSING_PHONENUMBER),
+ reply.getError().getCause().equals(Cause.MISSING_PHONENUMBER));
+ }
+
+ @Test
+ public void testSearchByPhoneNumberInvalid() {
+ final SearchByPhoneNumberRequest request = SearchByPhoneNumberRequest.newBuilder()
+ .setPhoneNumber(Util.INVALID_PHONENUMBER).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.INVALID_PHONENUMBER))).build();
+
+ given(accountService.searchByPhoneNumber(request.getPhoneNumber())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByPhoneNumber(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.INVALID_PHONENUMBER),
+ reply.getError().getCause().equals(Cause.INVALID_PHONENUMBER));
+ }
+
+ @Test
+ public void testSearchByEmail() throws ExecutionException, InterruptedException {
+ final SearchByEmailRequest request = SearchByEmailRequest.newBuilder()
+ .setEmail(Util.EMAIL).build();
+
+ SearchResponse response = savedResponse;
+
+ given(accountService.searchByEmail(request.getEmail())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByEmail(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain last name '%s'", Util.LAST_NAME.toString()),
+ reply.getSearchResultDetails().getLastName().equals(Util.LAST_NAME.toString()));
+ }
+
+ @Test
+ public void testSearchByEmailNotFound() throws ExecutionException, InterruptedException {
+ final SearchByEmailRequest request = SearchByEmailRequest.newBuilder()
+ .setEmail(Util.EMAIL).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.EMAIL_NOT_FOUND))).build();
+
+ given(accountService.searchByEmail(request.getEmail())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByEmail(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", biz.nynja.search.grpc.ErrorResponse.Cause.EMAIL_NOT_FOUND),
+ reply.getError().getCause().equals(biz.nynja.search.grpc.ErrorResponse.Cause.EMAIL_NOT_FOUND));
+ }
+
+ @Test
+ public void testSearchByEmailBadRequest() throws ExecutionException, InterruptedException {
+ final SearchByEmailRequest request = SearchByEmailRequest.newBuilder().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByEmail(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.MISSING_EMAIL),
+ reply.getError().getCause().equals(Cause.MISSING_EMAIL));
+ }
+
+ @Test
+ public void testSearchByEmailInvalid() {
+ final SearchByEmailRequest request = SearchByEmailRequest.newBuilder()
+ .setEmail(Util.INVALID_EMAIL).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.INVALID_EMAIL))).build();
+
+ given(accountService.searchByEmail(request.getEmail())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByEmail(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.INVALID_EMAIL),
+ reply.getError().getCause().equals(Cause.INVALID_EMAIL));
+ }
+
+ @Test
+ public void testSearchByQrCode() throws ExecutionException, InterruptedException {
+ final SearchByQrCodeRequest request = SearchByQrCodeRequest.newBuilder()
+ .setQrCode(Util.QR_CODE).build();
+
+ SearchResponse response = savedResponse;
+
+ given(accountService.searchByQrCode(request.getQrCode())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByQrCode(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain last name '%s'", Util.LAST_NAME.toString()),
+ reply.getSearchResultDetails().getLastName().equals(Util.LAST_NAME.toString()));
+ }
+
+ @Test
+ public void testSearchByQrCodeNotFound() throws ExecutionException, InterruptedException {
+ final SearchByQrCodeRequest request = SearchByQrCodeRequest.newBuilder()
+ .setQrCode(Util.QR_CODE).build();
+
+ SearchResponse response = SearchResponse.newBuilder().setError((ErrorResponse.newBuilder().setCause(Cause.QR_CODE_NOT_FOUND))).build();
+
+ given(accountService.searchByQrCode(request.getQrCode())).willReturn(response);
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByQrCode(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", biz.nynja.search.grpc.ErrorResponse.Cause.QR_CODE_NOT_FOUND),
+ reply.getError().getCause().equals(biz.nynja.search.grpc.ErrorResponse.Cause.QR_CODE_NOT_FOUND));
+ }
+
+ @Test
+ public void testSearchByQrCodeBadRequest() throws ExecutionException, InterruptedException {
+ final SearchByQrCodeRequest request = SearchByQrCodeRequest.newBuilder().build();
+
+ final SearchServiceGrpc.SearchServiceBlockingStub searchServiceBlockingStub = SearchServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+
+ final SearchResponse reply = searchServiceBlockingStub.searchByQrCode(request);
+
+ assertNotNull("Reply should not be null", reply);
+ assertTrue(String.format("Reply should contain cause '%s'", Cause.MISSING_QR_CODE),
+ reply.getError().getCause().equals(Cause.MISSING_QR_CODE));
+ }
}
diff --git a/src/test/java/biz/nynja/search/Util.java b/src/test/java/biz/nynja/search/Util.java
index 8bf2aaed0f7c000d07d457b51755d2d1cd6a6c30..9b9f255dd2bb4fda0187ce2771d003a7ebd9dcdb 100644
--- a/src/test/java/biz/nynja/search/Util.java
+++ b/src/test/java/biz/nynja/search/Util.java
@@ -1,32 +1,46 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+
package biz.nynja.search;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
-import biz.nynja.search.models.AccountInfo;;
+import com.google.protobuf.ByteString;
+
+import biz.nynja.search.grpc.SearchResponse;
+import biz.nynja.search.grpc.SearchResultDetails;
+
+/**
+ * Unit tests variables, beans and help methods.
+ */
@TestConfiguration
public class Util {
- public static final Long ID = 1L;
- public static final String EMAIL = "email@test.com";
- public static final String PASSWORD = "abc";
+ public static final String USERNAME = "TomJohns";
+ public static final String PHONE_NUMBER = "GB:448873598834";
+ public static final String EMAIL = "p_petrov@abv.bg";
+ public static final String QR_CODE = "QRcoded";
+ public static final String INVALID_USERNAME = "Tom-Johns";
+ public static final String INVALID_PHONENUMBER = "GB:44887359883"; // one DTMF less
+ public static final String INVALID_EMAIL = "p_petrov.@abv.bg";
- @Bean
- public AccountInfo newAccount() {
- AccountInfo accountInfo = new AccountInfo();
- accountInfo.setId(ID);
- accountInfo.setEmail(EMAIL);
- accountInfo.setPassword(PASSWORD);
- return accountInfo;
- }
+ public static final String AVATAR_STRING = "avatar-TomJohns";
+ public static final String FIRST_NAME = "Tom";
+ public static final String LAST_NAME = "Johns";
@Bean
- public AccountInfo savedAccount() {
- AccountInfo accountInfo = new AccountInfo();
- accountInfo.setId(ID);
- accountInfo.setEmail(EMAIL);
- accountInfo.setPassword(PASSWORD);
- return accountInfo;
+ public SearchResponse savedResponse() {
+ SearchResultDetails searchResultDetails = SearchResultDetails.newBuilder()
+ .setAvatar(ByteString.copyFrom(Util.AVATAR_STRING.getBytes()))
+ .setFirstName(Util.FIRST_NAME)
+ .setLastName(Util.LAST_NAME)
+ .build();
+ SearchResponse response = SearchResponse.newBuilder()
+ .setSearchResultDetails(searchResultDetails).build();
+ return response;
}
+
}