Java Spring Boot ile GraphQL

Abdulkerim Karaman
alBarakaTech Global
4 min readApr 25, 2020

GraphQL nedir sorusuna daha önceki makelemizde cevap vermiştik. İlgili makaleye aşağıdaki linkten ulaşabilirsiniz.

Spring Boot ise java tarafında popüler olarak kullanılan bir framework’dür. Bunun yanında spring-cloud-netflix ürünü open source olarak Netflix firması tarafından github üzerinden sunulmaktadır. Repo: https://github.com/spring-cloud/spring-cloud-netflix

Asıl konumuz GraphQL olduğu için bu kısımlara fazla girmeyeceğim. Spring Boot tarafında daha fazla bilgi için diğer makalelerime göz atabilirsiniz.

Demo uygulamamız için https://start.spring.io/ adresine girerek bir tane product-service oluşturalım.

Projemize ilk etapta 4 tane dependencies ekliyoruz. Bunlar sırasıyla şu şekilde:

1- Spring Web: Bir rest projesi oluşturacağımız için bunu ekliyoruz.

2-Spring Data JPA: Arka tarafta repository patern için ekliyoruz.

3-H2 Database: Uygulama data’larını saklayacağımız basit bir in-memory database.

4-Lombok: Proje içinde geter, seter, constructor işlemlerini otomatik yapmak için ekliyoruz.

İndirdiğimiz projeyi bir IDE yardımı ile açarak pom.xml dosyasına aşağıdaki dependencies’leri ekleyelim.

<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>

<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>

<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>

Özellikle versiyonlara dikkat edelim, uyumsuzluk sorunu çıkabiliyor.

Önce entity klasörü altına entity’mizi (vehicle) ekleyelim.

@Entity
@Table(name = "vehicle")
@Getter
@Setter
public class Vehicle implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(length = 100, name = "vehicle_type")
private String type;

@Column(length = 100, name = "model_code")
private String modelCode;

@Column(length = 100, name = "brand_name")
private String brandName;

@Column(length = 100, name = "launch_date")
private Date launchDate;
}

Database’den type’a göre kayıtları okumak için repository’imizi oluşturarak getByTypeLike methodu ekleyelim. Burada methodumuz dışardan bir type alacak ve bu type’a uyan kayıtları geri döndürecek. (Repository’imizin JpaRepository’den extends edildiğine dikkat edelim.)

public interface VehicleRepository  extends JpaRepository<Vehicle, Long> {

List<Vehicle> getByTypeLike(String type);
}

Şimdide db’ye kayıt eklemek için bir DTO tnımlayalım. DTO tanımlarken geter ve seter’lar için annotation kısmında lombark’ın Data annotation’u geçiyoruz.

import lombok.Data;


@Data
public class VehicleDto {
private String type;
private String modelCode;
private String brandName;
}

Şimdi geçelim en öncemli kısıma. Yazacağımız methodları dışarı açmak için 2 tane resolver oluşturacağız. Resolver’ları controller olarak düşünebilirsiniz.

Kayıtları okumak için GraphQLQueryResolver’dan türetilmiş VehicleQueryResolver dosyası aşağıdaki gibidir. Client’dan gelen type’ı repository’e geçiyoruz ve dönen response’u client’a dönüyoruz. (Aynı controller’larda yaptığımız gibi.)

@Component
@RequiredArgsConstructor
public class VehicleQueryResolver implements GraphQLQueryResolver {

private final VehicleRepository _vehicleRepository;

public List<Vehicle> getVehicles(String type) {
return _vehicleRepository.getByTypeLike(type);
}
}

DB ye kayıt yazmak için GraphQLMutationResolver’dan türetilmiş VehicleMutationResolver dosyası aşağıdaki gibidir. Client’dan gelen vehicle DTO’sunu repository’e gönderiyoruz ve dönen response’u client’a iletiyoruz.

@Component
@RequiredArgsConstructor
public class VehicleMutationResolver implements GraphQLMutationResolver {

private final VehicleRepository _vehicleRepository;

public Vehicle createVehicle(VehicleDto vehicleDto){
return _vehicleRepository.save(dtoToEntity(vehicleDto));
}

private Vehicle dtoToEntity(VehicleDto vehicleDto){
Vehicle vehicle=new Vehicle();
vehicle.setBrandName(vehicleDto.getBrandName());
vehicle.setLaunchDate(new Date());
vehicle.setModelCode(vehicleDto.getModelCode());
vehicle.setType(vehicleDto.getType());
return vehicle;
}
}

Artık son aşamaya geldik. Resources altına vehicle.graphqls adında bir şema oluşturuyoruz. VehicleDto ve Vehicle objelerimizin proplarını içeren şemaları burada tanıtıyoruz. Ardından Query kısmında data okurken kullanacağımız method ve aldıkları parametreleri belirtiyoruz. Mutation kısmında ise db’ye kayıt yapacağımız methodu ve alacağı parametreleri belirliyoruz.

type Vehicle {
id: ID!,
type: String!,
modelCode: String,
brandName: String,
launchDate: String
}

input VehicleDto {
type: String!,
modelCode: String!,
brandName: String
}

type Query {
getVehicles(type: String):[Vehicle]
getById(id: ID):Vehicle
}

type Mutation {
createVehicle(vehicle: VehicleDto):Vehicle
}

Buraya kadar kodlama işlemlerimizi tamamlamış bulunuyoruz. Şimdi test edebiliriz. Uygulamayı çalıştırdığınızda http://localhost:8090/graphql adresinden grqphql sorgusu atabileceğimiz web tool’una erişebilir veya postman üzerinden de bu işlemi yapabilirsiniz.

Önce bir data kaydedelim.

Sol tarafdaki mutation queryimiz ile db ye kayıt ekliyoruz ve ilgili graphql api’si bize bir response dönüyor. Dönen bu response içinde db ye eklenen kayıt yer alıyor.

Şimdi eklediğimiz bu kaydı okuyabiliriz. Okuma işlemi içinde bir query yazmamız yeterli. Görüldüğü üzere getVehicle methoduna type olarak 14 geçtiğimizde type’ı 14 olan kayıt listelenmektedir. Ayrıca listelenen bu kaydın hangi proplarını okumak istiyorsak scope içinde belirtiyoruz.

Evet uygulamamız başarılı şekilde çalıştı.

Github Repo:

Faydalı olması dileğiyle hoşçakalın..

--

--