[31.01.20] Function Endpoints and finalising GraphQL

This commit is contained in:
andyjk15 2020-01-31 21:34:35 +00:00
parent ea49e080a3
commit 5afa063e75
23 changed files with 265 additions and 452 deletions

View File

@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>. <https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -1,2 +1,3 @@
# db-gateway # Cryptosky Database Gateway
Database Gatway with a GraphQL API Projects Database Gateway service that is a gateway to the database cluster, using GraphQL API.

240
pom.xml
View File

@ -1,72 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<modelVersion>4.0.0</modelVersion> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cryptosky.me</groupId> <groupId>cryptosky.me</groupId>
<artifactId>db-gateway</artifactId> <artifactId>db-gateway</artifactId>
<version>0.0.1</version> <version>0.0.1</version>
<name>db-gateway</name> <name>DB Gateway</name>
<description>Database Cluster Gateway with a GraphQL API</description> <description>Database Cluster Gateway with a GraphQL API</description>
<properties> <parent>
<java.version>1.8</java.version> <groupId>org.springframework.boot</groupId>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version> <artifactId>spring-boot-starter-parent</artifactId>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-groovy-templates</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency> <!-- Web Sockets -->
<groupId>org.springframework.boot</groupId> <dependency>
<artifactId>spring-boot-starter-data-jdbc</artifactId> <groupId>org.springframework.boot</groupId>
</dependency> <artifactId>spring-boot-starter-web</artifactId>
<dependency> </dependency>
<groupId>org.springframework.boot</groupId> <dependency>
<artifactId>spring-boot-starter-data-jpa</artifactId> <groupId>org.springframework.boot</groupId>
</dependency> <artifactId>spring-boot-starter-websocket</artifactId>
<dependency> </dependency>
<groupId>com.h2database</groupId> <dependency>
<artifactId>h2</artifactId> <groupId>org.springframework.cloud</groupId>
<scope>runtime</scope> <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency> <!-- Persistent Data -->
<groupId>org.projectlombok</groupId> <dependency>
<artifactId>lombok</artifactId> <groupId>org.springframework.boot</groupId>
<optional>true</optional> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency> <!-- GraghQL -->
<dependency>
<groupId>com.graphql-java</groupId> <groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId> <artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version> <version>5.0.2</version>
@ -82,76 +62,78 @@
<version>5.0.2</version> <version>5.0.2</version>
</dependency> </dependency>
<dependency> <!-- Local database -->
<groupId>com.graphql-java</groupId> <dependency>
<artifactId>graphql-java-servlet</artifactId> <groupId>com.h2database</groupId>
<version>4.0.0</version> <artifactId>h2</artifactId>
</dependency> <scope>runtime</scope>
<dependency> </dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency> <!-- Database -->
<groupId>javax.xml.bind</groupId> <dependency>
<artifactId>jaxb-api</artifactId> <groupId>org.postgresql</groupId>
<version>2.3.0</version> <artifactId>postgresql</artifactId>
</dependency> <scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.projectlombok</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>lombok</artifactId>
<scope>test</scope> <version>1.18.8</version>
<exclusions> <optional>true</optional>
<exclusion> </dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement> <!-- Testing -->
<dependencies> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.cloud</groupId> <artifactId>spring-boot-starter-groovy-templates</artifactId>
<artifactId>spring-cloud-dependencies</artifactId> </dependency>
<version>${spring-cloud.version}</version> <dependency>
<type>pom</type> <groupId>org.springframework.boot</groupId>
<scope>import</scope> <artifactId>spring-boot-starter-test</artifactId>
</dependency> <scope>test</scope>
</dependencies> <exclusions>
</dependencyManagement> <exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build> <dependencyManagement>
<finalName>Cryptosky DB Gateway</finalName> <dependencies>
<plugins> <dependency>
<plugin> <groupId>org.springframework.cloud</groupId>
<groupId>org.eclipse.jetty</groupId> <artifactId>spring-cloud-dependencies</artifactId>
<artifactId>jetty-maven-plugin</artifactId> <version>${spring-cloud.version}</version>
<version>9.4.6.v20170531</version> <type>pom</type>
</plugin> <scope>import</scope>
<plugin> </dependency>
<groupId>org.springframework.boot</groupId> </dependencies>
<artifactId>spring-boot-maven-plugin</artifactId> </dependencyManagement>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin> <build>
<artifactId>maven-war-plugin</artifactId> <finalName>Cryptosky DB Gateway</finalName>
<version>3.1.0</version> <plugins>
</plugin> <plugin>
</plugins> <groupId>org.eclipse.jetty</groupId>
</build> <artifactId>jetty-maven-plugin</artifactId>
<version>9.4.6.v20170531</version>
</project> </plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,13 +0,0 @@
package cryptosky.me.dbgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DbGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(DbGatewayApplication.class, args);
}
}

View File

@ -1,33 +0,0 @@
package cryptosky.me.dbgateway.exceptions.data;
import graphql.ErrorType;
import graphql.GraphQLError;
import graphql.language.SourceLocation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class cryptoPriceNotFoundException extends RuntimeException implements GraphQLError {
private Map<String, Object> extensions = new HashMap<>();
public cryptoPriceNotFoundException(String message, Long invalidId) {
super(message);
extensions.put("invalidId", invalidId);
}
@Override
public List<SourceLocation> getLocations() {
return null;
}
@Override
public Map<String, Object> getExtensions() {
return extensions;
}
@Override
public ErrorType getErrorType() {
return ErrorType.DataFetchingException;
}
}

View File

@ -1,48 +0,0 @@
package cryptosky.me.dbgateway.exceptions.service;
import graphql.ErrorType;
import graphql.GraphQLError;
import graphql.language.SourceLocation;
import graphql.ExceptionWhileDataFetching;
import java.util.List;
import java.util.Map;
public class GraphQLAdapterError implements GraphQLError {
private GraphQLError error;
public GraphQLAdapterError(GraphQLError error) {
this.error = error;
}
@Override
public Map<String, Object> getExtensions() {
return error.getExtensions();
}
@Override
public List<SourceLocation> getLocations() {
return error.getLocations();
}
@Override
public ErrorType getErrorType() {
return error.getErrorType();
}
@Override
public List<Object> getPath() {
return error.getPath();
}
@Override
public Map<String, Object> toSpecification() {
return error.toSpecification();
}
@Override
public String getMessage() {
return (error instanceof ExceptionWhileDataFetching) ? ((ExceptionWhileDataFetching) error).getException().getMessage() : error.getMessage();
}
}

View File

@ -1,9 +0,0 @@
package cryptosky.me.dbgateway.jpa.repository;
import cryptosky.me.dbgateway.jpa.entity.Vehicle;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface VehicleRepository extends JpaRepository<Vehicle, Integer> {
}

View File

@ -1,42 +0,0 @@
package cryptosky.me.dbgateway.models;
import lombok.*;
import javax.persistence.*;
import java.sql.Timestamp;
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ToString
@Getter
@Setter
@Builder
public class CryptoPriceModel {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "timestamp", nullable = false)
private Timestamp timestamp;
@Column(name = "type", nullable = false)
private String type;
@Column(name = "av_price", nullable = false)
private Long average_price;
@Column(name = "h_price", nullable = false)
private Long high_price;
@Column(name = "l_price", nullable = false)
private Long low_price;
@Column(name = "c_price", nullable = false)
private Long close_price;
@Column(name = "volume", nullable = false)
private Long volume;
}

View File

@ -1,20 +0,0 @@
package cryptosky.me.dbgateway.mutation;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import cryptosky.me.dbgateway.jpa.entity.Vehicle;
import cryptosky.me.dbgateway.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
@Component
public class VehicleMutation implements GraphQLMutationResolver {
@Autowired
private VehicleService vehicleService;
public Vehicle createVehicle(final LocalDate timestamp, final Long av_price, final Long h_price, final Long l_price, final Long c_price, final Long volume ) {
return this.vehicleService.createVehicle( timestamp, av_price, h_price, l_price, c_price, volume );
}
}

View File

@ -1,25 +0,0 @@
package cryptosky.me.dbgateway.query;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import cryptosky.me.dbgateway.jpa.entity.Vehicle;
import cryptosky.me.dbgateway.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class VehicleQuery implements GraphQLQueryResolver {
@Autowired
private VehicleService vehicleService;
public List<Vehicle> getVehicles(final int count) {
return this.vehicleService.getAllVehicles(count);
}
public Optional<Vehicle> getVehicle(final int id) {
return this.vehicleService.getVehicle(id);
}
}

View File

@ -1,9 +0,0 @@
package cryptosky.me.dbgateway.repository;
import cryptosky.me.dbgateway.models.CryptoPriceModel;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CryptoPriceRepository extends CrudRepository<CryptoPriceModel, Long> {
}

View File

@ -1,17 +0,0 @@
package cryptosky.me.dbgateway.resolvers.dataResolvers;
import com.coxautodev.graphql.tools.GraphQLResolver;
import cryptosky.me.dbgateway.models.CryptoPriceModel;
import cryptosky.me.dbgateway.repository.CryptoPriceRepository;
public class CryptoPriceResolver implements GraphQLResolver<CryptoPriceModel> {
private CryptoPriceRepository cryptoPriceRepository;
public CryptoPriceResolver( CryptoPriceRepository cryptoPriceRepository ) {
this.cryptoPriceRepository = cryptoPriceRepository;
}
// public CryptoPriceModel getPrice( Long id ) {
// return cryptoPriceRepository.findById( CryptoPriceModel );
// }
}

View File

@ -1,36 +0,0 @@
package cryptosky.me.dbgateway.resolvers.mutations;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import cryptosky.me.dbgateway.models.CryptoPriceModel;
import cryptosky.me.dbgateway.repository.CryptoPriceRepository;
import java.sql.Timestamp;
public class CryptoPriceMutation implements GraphQLMutationResolver {
private CryptoPriceRepository cryptoPriceRepository;
// public Mutation(CryptoPriceRepository cryptoPriceRepository) {
// this.cryptoPriceRepository = cryptoPriceRepository;
// }
public CryptoPriceModel newPriceEntry(Timestamp timestamp, String type, Long average_price, Long high_price, Long low_price, Long close_price, Long volume) {
CryptoPriceModel cryptoPriceModel = CryptoPriceModel.builder()
.timestamp(timestamp)
.type(type)
.average_price(average_price)
.high_price(high_price)
.low_price(low_price)
.close_price(close_price)
.volume(volume)
.build();
cryptoPriceRepository.save(cryptoPriceModel);
return cryptoPriceModel;
}
// public boolean deleteCrypto(Long id) {
// cryptoPriceRepository.delete(id);
// return true;
// }
}

View File

@ -1,45 +0,0 @@
package cryptosky.me.dbgateway.service;
import cryptosky.me.dbgateway.jpa.entity.Vehicle;
import cryptosky.me.dbgateway.jpa.repository.VehicleRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class VehicleService {
private final VehicleRepository vehicleRepository ;
public VehicleService(final VehicleRepository vehicleRepository) {
this.vehicleRepository = vehicleRepository ;
}
@Transactional
public Vehicle createVehicle( final LocalDate timestamp, final Long av_price, final Long h_price, final Long l_price, final Long c_price, final Long volume ) {
Vehicle vehicle = Vehicle.builder()
.timestamp(timestamp)
.average_price(av_price)
.high_price(h_price)
.low_price(l_price)
.close_price(c_price)
.volume(volume)
.build();
return this.vehicleRepository.save(vehicle);
}
@Transactional(readOnly = true)
public List<Vehicle> getAllVehicles(final int count) {
return this.vehicleRepository.findAll().stream().limit(count).collect(Collectors.toList());
}
@Transactional(readOnly = true)
public Optional<Vehicle> getVehicle(final int id) {
return this.vehicleRepository.findById(id);
}
}

View File

@ -1,4 +1,4 @@
package cryptosky.me.dbgateway; package cryptosky.me.graphql;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -1,4 +1,4 @@
package cryptosky.me.dbgateway.jpa.entity; package cryptosky.me.graphql.jpa.entity;
import lombok.*; import lombok.*;
@ -14,7 +14,7 @@ import java.time.LocalDate;
@Data @Data
@EqualsAndHashCode @EqualsAndHashCode
@Entity @Entity
public class Vehicle { public class CryptoPrice {
@Id @Id
@Column(name = "ID", nullable = false) @Column(name = "ID", nullable = false)
@ -24,6 +24,9 @@ public class Vehicle {
@Column(name = "timestamp", nullable = false) @Column(name = "timestamp", nullable = false)
private LocalDate timestamp; private LocalDate timestamp;
@Column(name = "symbol", nullable = false)
private String type;
@Column(name = "av_price", nullable = false) @Column(name = "av_price", nullable = false)
private Long average_price; private Long average_price;
@ -33,10 +36,10 @@ public class Vehicle {
@Column(name = "l_price", nullable = false) @Column(name = "l_price", nullable = false)
private Long low_price; private Long low_price;
@Column(name = "c_price", nullable = false) @Column(name = "c_price")
private Long close_price; private Long close_price;
@Column(name = "volume", nullable = false) @Column(name = "volume")
private Long volume; private Long volume;
private transient String formattedDate; private transient String formattedDate;
@ -44,4 +47,4 @@ public class Vehicle {
public String getFormattedDate() { public String getFormattedDate() {
return getTimestamp().toString(); return getTimestamp().toString();
} }
} }

View File

@ -0,0 +1,9 @@
package cryptosky.me.graphql.jpa.repository;
import cryptosky.me.graphql.jpa.entity.CryptoPrice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CryptoPriceRepository extends JpaRepository<CryptoPrice, Integer> {
}

View File

@ -0,0 +1,19 @@
package cryptosky.me.graphql.mutation;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import cryptosky.me.graphql.jpa.entity.CryptoPrice;
import cryptosky.me.graphql.service.CryptoPriceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CryptoPriceMutation implements GraphQLMutationResolver {
@Autowired
private CryptoPriceService cryptoPriceService;
public CryptoPrice createPrice( final String createdDate, final String type, final Long av_price,
final Long h_price, final Long l_price, final Long c_price, final Long volume ) {
return this.cryptoPriceService.createPrice(createdDate, type, av_price, h_price, l_price, c_price, volume);
}
}

View File

@ -0,0 +1,25 @@
package cryptosky.me.graphql.query;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import cryptosky.me.graphql.jpa.entity.CryptoPrice;
import cryptosky.me.graphql.service.CryptoPriceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class CryptoPriceQuery implements GraphQLQueryResolver {
@Autowired
private CryptoPriceService vehicleService;
public List<CryptoPrice> getVehicles(final int count) {
return this.vehicleService.getAllPrices(count);
}
public Optional<CryptoPrice> getVehicle(final int id) {
return this.vehicleService.getVehicle(id);
}
}

View File

@ -0,0 +1,69 @@
package cryptosky.me.graphql.service;
import cryptosky.me.graphql.jpa.entity.CryptoPrice;
import cryptosky.me.graphql.jpa.repository.CryptoPriceRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class CryptoPriceService {
private final CryptoPriceRepository cryptoPriceRepository;
public CryptoPriceService(final CryptoPriceRepository cryptoPriceRepository) {
this.cryptoPriceRepository = cryptoPriceRepository;
}
@Transactional
public CryptoPrice createPrice( final String createdDate, final String type, final Long av_price,
final Long h_price, final Long l_price, final Long c_price, final Long volume ) {
final CryptoPrice cryptoPrice = CryptoPrice.builder()
.timestamp(LocalDate.parse(createdDate))
.type(type)
.average_price(av_price)
.high_price(h_price)
.low_price(l_price)
.close_price(c_price)
.volume(volume)
.build();
return this.cryptoPriceRepository.save(cryptoPrice);
}
@Transactional(readOnly = true)
public List<CryptoPrice> getAllPrices(final int count) {
return this.cryptoPriceRepository.findAll().stream()
.limit(count)
.collect(Collectors.toList());
}
@Transactional(readOnly = true)
public List<CryptoPrice> getAllPricesByType(final int count, final String type) {
return this.cryptoPriceRepository.findAll().stream()
.filter(typeList -> typeList.getType().equals(type))
.limit(count)
.collect(Collectors.toList());
}
@Transactional(readOnly = true)
public Optional<CryptoPrice> getVehicle(final int id) {
return this.cryptoPriceRepository.findById(id);
}
@Transactional(readOnly = true)
public Optional<CryptoPrice> getPriceByCreatedDate(final String type, final String createdDate) {
return this.cryptoPriceRepository.findAll().stream()
.filter(typeList -> typeList.getType().equals(type))
.filter(createdDateList -> createdDateList.getTimestamp().equals(createdDate))
.findFirst();
}
// @Transactional(readOnly = true)
// public Optional<CryptoPrice> getprice
}

View File

@ -1 +0,0 @@

View File

@ -0,0 +1,19 @@
type CryptoPrice {
id: ID!,
timestamp: String!,
type: String,
average_price: Float!,
high_price: Float,
low_price: Float,
close_price: Float,
volume: Float
}
type Query {
vehicles(count: Int):[CryptoPrice]
vehicle(id: ID):CryptoPrice
}
type Mutation {
createVehicle(type: String!, average_price: Float!, high_price: Float, low_price: Float, close_price: Float, volume: Float):CryptoPrice
}

View File

@ -1,16 +0,0 @@
type Vehicle {
id: ID!,
type: String,
modelCode: String,
brandName: String,
launchDate: String
}
type Query {
vehicles(count: Int):[Vehicle]
vehicle(id: ID):Vehicle
}
type Mutation {
createVehicle(type: String!, modelCode: String!, brandName: String, launchDate: String):Vehicle
}