[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

@ -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.

80
pom.xml
View File

@ -1,7 +1,15 @@
<?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"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>cryptosky.me</groupId>
<artifactId>db-gateway</artifactId>
<version>0.0.1</version>
<name>DB Gateway</name>
<description>Database Cluster Gateway with a GraphQL API</description>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
@ -9,25 +17,15 @@
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>cryptosky.me</groupId>
<artifactId>db-gateway</artifactId>
<version>0.0.1</version>
<name>db-gateway</name>
<description>Database Cluster Gateway with a GraphQL API</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <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>
<!-- Web Sockets -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
@ -41,31 +39,13 @@
<artifactId>spring-cloud-starter-gateway</artifactId> <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency> </dependency>
<dependency> <!-- Persistent Data -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- GraghQL -->
<dependency> <dependency>
<groupId>com.graphql-java</groupId> <groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId> <artifactId>graphql-spring-boot-starter</artifactId>
@ -82,24 +62,32 @@
<version>5.0.2</version> <version>5.0.2</version>
</dependency> </dependency>
<!-- Local database -->
<dependency> <dependency>
<groupId>com.graphql-java</groupId> <groupId>com.h2database</groupId>
<artifactId>graphql-java-servlet</artifactId> <artifactId>h2</artifactId>
<version>4.0.0</version> <scope>runtime</scope>
</dependency> </dependency>
<!-- Database -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>org.postgresql</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>postgresql</artifactId>
<version>3.0.1</version> <scope>runtime</scope>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>org.projectlombok</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>lombok</artifactId>
<version>2.3.0</version> <version>1.18.8</version>
<optional>true</optional>
</dependency> </dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-groovy-templates</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
@ -146,12 +134,6 @@
<target>1.8</target> <target>1.8</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </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;

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
}