Spring Boot mikroservisinde strateji tasarım deseni ile wizard UI bileşenini yönetmek

Serdar A.
10 min readJul 4, 2023

--

Merhabalar;

For English : https://lastjavabuilder.medium.com/managing-the-wizard-ui-component-by-the-strategy-design-pattern-in-spring-boot-backend-service-7ad47ab750ae

İster monolitik bir uygulamanız olsun ister de microservis mimarisinde bir uygulamanız olsun, frontend uygulamanızda bir wizard UI component varsa ve bunu az sayıda endpoint ile backend tarafında yönetmek istiyorsanız, bunun strateji design pattern ile nasıl yapılabileceği ile ilgili bu yazım da backend tarafında örnek bir uygulama göstermek istiyorum.

Yaklaşım tarzım ve kodlarım elbette geliştirilebilir ancak bir fikir edinmesi açısında burada sizinle paylaşmak istiyorum.

O zaman başlayalım :)

Diyelim ki elimizde aşağıdaki gibi bir wizard UI componentimiz var frontend uygulamamızda. Çizimler için özür dilerim :))

1.ekranda product için temel bilgiler giriş ekranı

2.ekranda product için detay bilgiler giriş ekranı

3.ekranda product için özellikler girebileceğimiz giriş ekranı

4.ekranda product için kategorisi için giriş ekranı

5.ekranda product için firma bilgisi için giriş ekranı

Her ekran için ayrı ayrı get, post,put vb api ler yazmak yerine daha kısa yoldan yapmak için strateji tasarım deseninden yararlanabiliriz. Bu uygulamada 1 tane get api 1 tane de post api tanımlayacağız. Bu 2 api ile ekranlarımızı yönetmeye çalışacağız.

O zaman backend servisimizi yazmaya başlayalım.

Öncelikle spring boot uygulamamızda wizard daki her ekran için hangi ekranı yöneteceğimizi belirlemek için 1 tane enum class yaratıyoruz.

public enum WizardSceenEnum {

PRODUCT_INFO_SCREEN(1,"ProductInfo","Entering infos of product base"),
PRODUCT_DETAIL_SCREEN(2,"ProductDetail","Entering info of product details"),
PRODUCT_CATEGORY_SCREEN(3,"ProductCategory","Entering category info of product"),
PRODUCT_COMPANY_SCREEN(4,"ProductCompany","Entering company info of product"),
PRODUCT_SPECIFICATION_SCREEN(5,"ProductSpecification","Entering specifications of product");

private Integer order;
private String screenKey;
private String screenDescription;

WizardSceenEnum(Integer order, String screenKey, String screenDescription) {
this.order = order;
this.screenKey = screenKey;
this.screenDescription = screenDescription;
}

WizardSceenEnum findScreenByOrderId(Integer orderIndex)
{
for(WizardSceenEnum wizardSceenEnum : values())
{
if(wizardSceenEnum.getOrder().equals(orderIndex))
{
return wizardSceenEnum;
}
}

return null;
}

WizardSceenEnum findScreenByKey(String key)
{
for(WizardSceenEnum wizardSceenEnum : values())
{
if(wizardSceenEnum.getScreenKey().equals(key))
{
return wizardSceenEnum;
}
}

return null;
}

public Integer getOrder() {
return order;
}

public String getScreenKey() {
return screenKey;
}

public String getScreenDescription() {
return screenDescription;
}
}

enum daki her değer 1 ekrana denk gelmektedir.

  • ekran sırasını belirtmek için order,
  • ekranı tanımlayan bir key için screenKey,
  • ekranı ile ilgili bir açıklama için screenDescription

değişkenler tanımladık.

api den gelen isteğin create mi yoksa update mi olduğunu tanımlamak için gene bir enum tanımlayacağız.

public enum WizardScreenRequestTypeEnum {

CREATE("CREATE"),
UPDATE("UPDATE");

private String requestType;

WizardScreenRequestTypeEnum( String requestType) {
this.requestType = requestType;
}

WizardScreenRequestTypeEnum getScreenRequestTypeByKey(String key)
{
for (WizardScreenRequestTypeEnum wizardScreenRequestTypeEnum: values())
{
if(wizardScreenRequestTypeEnum.getRequestType().equals(key))
{
return wizardScreenRequestTypeEnum;
}
}

return null;
}

public String getRequestType() {
return requestType;
}
}

frontend tarafından atılan istek bir post isteği mi yoksa bir put isteğimi olduğunu belirtmek için bu şekilde bir enum tanımlıyoruz.
Aslında bu kısımda ayrıca put methodu tanımlamamak için tek bir post methodu kullanmak için böyle bir enum değeri tanımladım.

Sıra geldi her ekranı yönetmek gerekli olan DTO ları tanımlamaya.

Öncelikle bir tane BaseDTO tanımlıyorum.

@Data
public class BaseDTO implements Serializable {

private Long id;
}

Daha sonra ekranlarım için DTO ları tanımlamaya başlıyorum.

Product ekranı için

@Data
@EqualsAndHashCode(callSuper = false)
public class ProductDTO extends BaseDTO {

private String productName;
private String productCode;
private String productTitle;
private String productDetail;
}
  • Product detail ekranı için aynı DTO yu kullanabilirim.

Product Specification ekranı için

@Data
@EqualsAndHashCode(callSuper = false)
public class SpecificationDTO extends BaseDTO {

private String description;
}

Product Category ekranı için

@Data
@EqualsAndHashCode(callSuper = false)
public class CategoryDTO extends BaseDTO {

private String categoryName;
}

Product Company ekranı için

@Data
@EqualsAndHashCode(callSuper = false)
public class CompanyDTO extends BaseDTO {

private String companyName;
}

Tüm bu DTO ları wrap eden bir tane daha DTO tanımlamamız gerekiyor.

Bu DTO get ve post apimiz için return edecek.

WizardScreenDTO

@Data
@EqualsAndHashCode(callSuper = false)
public class WizardScreenDTO extends BaseDTO {

private ProductDTO productDTO;
private CategoryDTO categoryDTO;
private CompanyDTO companyDTO;
private List<SpecificationDTO> specificationDTOList = new LinkedList<>();

}

Son olarak post methodu için body parametresi olarak bir tane daha DTO tanımlamamız gerekiyor.

WizardRequestDTO

@Data
public class WizardRequestDTO implements Serializable {

private WizardSceenEnum sceenEnum;
private WizardScreenRequestTypeEnum requestTypeEnum;
private WizardScreenDTO wizardScreenDTO;
}

Bu DTO yu açıklamak gerekirse:

  • sceenEnum : Hangi ekranı yöneteceğimizi belirtiyor.
  • requestTypeEnum : İsteğin bir create mi yoksa update mi olduğunu belirtiyor.
  • wizardScreenDTO : İlgili ekranın da bilgilerini barındıran DTO yu wrap eden DTO

Şimdi bize bir tane tüm bu ekranları ayrı ayrı yöneten classların implement edeceği bir tane interface lazım.

IWizardScreenService

public interface IWizardScreenService {

<T extends BaseDTO> T getWizard(Long id);

<T extends BaseDTO> T createModelWizard(WizardScreenDTO createdWizardScreenDTO);

<T extends BaseDTO> T updateModelWizard(WizardScreenDTO updateddWizardScreenDTO);

WizardSceenEnum getScreenName();
}

methodları açıklamak gerekirse:

  • getWizard : id parametresi ne ise (productId, companyId, categoryId veya productId üzerinden child tablolara erişim sağlayabileceiğimiz id değeri vs ) onunla ilgili veritabanından veya ilgili başka bir servisten bilgi getiren method.
  • createModelWizard : hangi ekran ile save işlemleri yapılacaksa bu method ile yapılacak. Bu method WizardScreenDTO tipinde wrap class parametre alıyor. Bu Wrap class içinde istediğimiz ekrana ait DTO lar bulunmaktadır.
  • updateModelWizard : hangi ekran ile update işlemleri yapılacaksa bu method ile yapılacak.Bu method WizardScreenDTO tipinde wrap class parametre alıyor. Bu Wrap class içinde istediğimiz ekrana ait DTO lar bulunmaktadır.
  • getScreenName : Hangi ekran için işlem yapılıyorsa o ekran ile ilgili ekranın bilgisi return eden method.

Bu class da methodların dönüş tiplerini generic yaptım ancak daha farklı da yapabilirsiniz. BaseDTO kullanma amaçlarımdan bir tanesi de bu aslında.

Bu interface den daha sonra ekranlarımızı yöneten, kendi logic lerini ayrı ayrı ele aldığımız class lar yaratacağız. Ama öncelikle runtime da isteğimize göre hangi ekranın ele alınmasını sağlamamız gerekiyor. Bunun için bir tane factory class ına ihtiyacımız var.

WizardFactoryService

@Service
public class WizardFactoryService {

private Map<WizardSceenEnum, IWizardScreenService> wizardScreens;

@Autowired
public WizardFactoryService(Set<IWizardScreenService> IWizardScreenServiceSet)
{
createScreenWizard(IWizardScreenServiceSet);
}

public IWizardScreenService getScreenWizard(WizardSceenEnum wizardSceenEnum)
{
return wizardScreens.get(wizardSceenEnum);
}

private void createScreenWizard(Set<IWizardScreenService> IWizardScreenServiceSet) {

wizardScreens = new HashMap<>();
IWizardScreenServiceSet.forEach(projectWizardService -> wizardScreens.put(projectWizardService.getScreenName(),projectWizardService));
}
}

Bu factory class ının aslında yaptığı şey gönderdiğimiz wizardSceenEnum parametresine göre bu enum değeri ile ilişkili ekranı yöneten class ı crete edecek ve bize döndürecek. İlerleyen satırlarda tam olarak nasıl çalıştığını anlayacaksınız umarım.

Şimdi her ekranı yöneten, kendi ayrı logic kısmı olan ekran class larımızı yazmaya başlayabiliriz.

Öncelikle ilk ekranımız için iş katmanını yöneten ProductInfoScreenService class ımızı yazıyoruz.

ProductInfoScreenService

@Service
public class ProductInfoScreenService implements IWizardScreenService {

@Override
public <T extends BaseDTO> T getWizard(Long id) {

//id -> product table id
//get info from database or get another microservice

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO productDTO = createProductDTO(id);

wizardScreenDTO.setProductDTO(productDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T createModelWizard(WizardScreenDTO createdProjectDTO) {

ProductDTO productDTO = createdProjectDTO.getProductDTO();

//save dto for entity or send another service get response

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO createdProductDTO = saveProductDTO(productDTO);

wizardScreenDTO.setProductDTO(createdProductDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T updateModelWizard(WizardScreenDTO updatedProjectDTO) {

ProductDTO productDTO = updatedProjectDTO.getProductDTO();

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO updatedProductDTO = updateProductDTO(productDTO);

wizardScreenDTO.setProductDTO(updatedProductDTO);
return (T) wizardScreenDTO;
}

@Override
public WizardSceenEnum getScreenName() {
return WizardSceenEnum.PRODUCT_INFO_SCREEN;
}

private ProductDTO createProductDTO(Long id) {

ProductDTO productDTO = new ProductDTO();
productDTO.setId(id);
productDTO.setProductName("product 1");
productDTO.setProductCode("p1");
productDTO.setProductTitle("product1 title");

return productDTO;
}

private ProductDTO saveProductDTO(ProductDTO productDTO) {

ProductDTO createdDTO = new ProductDTO();
createdDTO.setProductName(productDTO.getProductName());
createdDTO.setProductCode(productDTO.getProductCode());
createdDTO.setProductTitle(productDTO.getProductTitle());

//save database
createdDTO.setId(2l);
return createdDTO;
}

private ProductDTO updateProductDTO(ProductDTO productDTO) {

//update database
return productDTO;
}
}

Bu class IWizardScreenService implement eder.

Bu class da database işlemleri yapabileceğiniz gibi başka bir microservise istek atıp çeşitli işlemler yapabilirsiniz. Ben örnek olması açısından logic kısmını basit tuttum. Bu class da ilk ekranda yer alan input değerleri için logic işlemleri yaptım.

Örnek olarak daha küçük sorgular yazıp buna göre bu ekran için gerekli minimum bilgiyi veritabanından çekebilirsiniz.

Şimdi ikinci ekranımızı yöneten class ımızı yazalım

ProductDetailScreenService

@Service
public class ProductDetailScreenService implements IWizardScreenService {

@Override
public <T extends BaseDTO> T getWizard(Long id) {

//id -> product table id
//get info from database or get from another microservice

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO productDetailDTO = createProductDetailDTO(id);
wizardScreenDTO.setProductDTO(productDetailDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T createModelWizard(WizardScreenDTO createdProjectDetailDTO) {

ProductDTO productDTO = createdProjectDetailDTO.getProductDTO();

//save database or send another service get response

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO createdProductDetailDTO = saveProductDetailDTO(productDTO);

wizardScreenDTO.setProductDTO(createdProductDetailDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T updateModelWizard(WizardScreenDTO updatedProjectDTO) {

ProductDTO productDTO = updatedProjectDTO.getProductDTO();

//save database or send another service

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
ProductDTO updatedProductDetailDTO = updateProductDetailDTO(productDTO);

wizardScreenDTO.setProductDTO(updatedProductDetailDTO);

return (T) wizardScreenDTO;
}

@Override
public WizardSceenEnum getScreenName() {
return WizardSceenEnum.PRODUCT_DETAIL_SCREEN;
}

private ProductDTO createProductDetailDTO(Long id) {

ProductDTO productDTO = new ProductDTO();
productDTO.setId(id);
productDTO.setProductDetail("product 1 detail info ");

return productDTO;

}

private ProductDTO saveProductDetailDTO(ProductDTO productDTO) {

Long id = 1l; // get productId
ProductDTO createdDTO = new ProductDTO();
createdDTO.setId(id);
createdDTO.setProductDetail(productDTO.getProductDetail());

//save database
return createdDTO;

}

private ProductDTO updateProductDetailDTO(ProductDTO productDTO) {

//update database
return productDTO;
}
}

Bu class da logic olarak aslında Product objesinin diğer bilgileri değil, sadece description bilgisini yöneten işlemler yapıyor.

Sırada üçüncü ekranımızı yöneten class a ihtiyaç var

ProductSpecificationScreenService

@Service
public class ProductSpecificationScreenService implements IWizardScreenService {

@Override
public <T extends BaseDTO> T getWizard(Long id) {

//id -> product table id
//get info from database with or another microservice

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
List<SpecificationDTO> specificationDTOList = createProductSpecificationList();
wizardScreenDTO.setSpecificationDTOList(specificationDTOList);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T createModelWizard(WizardScreenDTO createdProjectSpecDTO) {

ProductDTO productDTO = createdProjectSpecDTO.getProductDTO();

List<SpecificationDTO> createSpecificationDTOList = createdProjectSpecDTO.getSpecificationDTOList();

AtomicLong counter = new AtomicLong(100);

createSpecificationDTOList.forEach(specificationDTO -> {
specificationDTO.setId(counter.getAndIncrement());
});

//save product specification table with createSpecificationDTOList

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setSpecificationDTOList(createSpecificationDTOList);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T updateModelWizard(WizardScreenDTO updatedProjectSpecDTO) {

ProductDTO productDTO = updatedProjectSpecDTO.getProductDTO();

List<SpecificationDTO> updateSpecificationDTOList = updatedProjectSpecDTO.getSpecificationDTOList();

//update product specification table with updateSpecificationDTOList

updateSpecificationDTOList.forEach(specificationDTO -> {

specificationDTO.setDescription(specificationDTO + " updated");
});

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setSpecificationDTOList(updateSpecificationDTOList);

return (T) wizardScreenDTO;
}

@Override
public WizardSceenEnum getScreenName() {
return WizardSceenEnum.PRODUCT_SPECIFICATION_SCREEN;
}

private List<SpecificationDTO> createProductSpecificationList() {

List<SpecificationDTO> list = new ArrayList<>();

SpecificationDTO dto1 = createSpecificationDTO(300l,"spec 1");
SpecificationDTO dto2 = createSpecificationDTO(400l,"spec 2");

list.add(dto1);
list.add(dto2);

return list;

}

private SpecificationDTO createSpecificationDTO(Long specId, String specName) {

SpecificationDTO dto = new SpecificationDTO();
dto.setId(specId);
dto.setDescription(specName);

return dto;
}
}

Bu class da Product objesinin diğer bilgilerini değil sadece Specification bilgilerini yöneten işlemler yapıyor.

Sırada kategori ekranı için servis yazmaya

ProductCategoryScreenService

@Service
public class ProductCategoryScreenService implements IWizardScreenService {
@Override
public <T extends BaseDTO> T getWizard(Long id) {

//id -> product table id or category id
//get info from database or get another microservice

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
CategoryDTO categoryDTO = new CategoryDTO();
categoryDTO.setId(2l);
categoryDTO.setCategoryName("Category 1");

wizardScreenDTO.setCategoryDTO(categoryDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T createModelWizard(WizardScreenDTO createdCategoryDTO) {

CategoryDTO createCategory = createdCategoryDTO.getCategoryDTO();
ProductDTO productDTO = createdCategoryDTO.getProductDTO();

// save product table with category in database or send another service get response

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setCategoryDTO(createCategory);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T updateModelWizard(WizardScreenDTO updatedCategoryDTO) {

CategoryDTO updateCategory = updatedCategoryDTO.getCategoryDTO();
ProductDTO productDTO = updatedCategoryDTO.getProductDTO();

//update product with category in database or send another service get response
WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setCategoryDTO(updateCategory);

return (T) wizardScreenDTO;
}

@Override
public WizardSceenEnum getScreenName() {
return WizardSceenEnum.PRODUCT_CATEGORY_SCREEN;
}
}

Sırada son ekran olan Company ile ilgili işlemleri yöneten class

ProductCompanyScreenService

@Service
public class ProductCompanyScreenService implements IWizardScreenService {

@Override
public <T extends BaseDTO> T getWizard(Long id) {

//id -> product table id or company id
//get info from database or get another microservice

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
CompanyDTO companyDTO = new CompanyDTO();
companyDTO.setId(100l);
companyDTO.setCompanyName("Company 100");

wizardScreenDTO.setCompanyDTO(companyDTO);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T createModelWizard(WizardScreenDTO createdCompanyDTO) {

CompanyDTO createCompany = createdCompanyDTO.getCompanyDTO();
ProductDTO productDTO = createdCompanyDTO.getProductDTO();

// save product table with category in database or send another service get response

WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setCompanyDTO(createCompany);

return (T) wizardScreenDTO;
}

@Override
public <T extends BaseDTO> T updateModelWizard(WizardScreenDTO updatedCompanyDTO) {

CompanyDTO updateCompany= updatedCompanyDTO.getCompanyDTO();
ProductDTO productDTO = updatedCompanyDTO.getProductDTO();

//update product with category in database or send another service get response
WizardScreenDTO wizardScreenDTO = new WizardScreenDTO();
wizardScreenDTO.setProductDTO(productDTO);
wizardScreenDTO.setCompanyDTO(updateCompany);

return (T) wizardScreenDTO;
}

@Override
public WizardSceenEnum getScreenName() {
return WizardSceenEnum.PRODUCT_COMPANY_SCREEN;
}
}

Bu class larda dikkat ederseniz getScreenName() methodunda her ekrana ilişkin enum değerini dönüyorum.

Tüm bunları yaptıktan sonra artık Controller ve bu Controller ı yöneten Service class ımızı yazabiliriz.

Servis class ımız için öncelikle bir tane interface e ihtiyaç var

IWizardService

public interface IWizardService {

ResponseEntity<WizardScreenDTO> postWizard(WizardRequestDTO wizardRequestDTO);

ResponseEntity<WizardScreenDTO> getWizard(Long id, WizardSceenEnum wizardSceenEnum);
}

Daha önce de dediğim gibi iki tane endpoint imiz olacak bu iki endpoint için de iki tane servis methodumuz olacak

Şimdi bu interface i implement eden servis class ımızı yazabiliriz.

WizardService

@Service
public class WizardService implements IWizardService {

private final WizardFactoryService wizardFactoryService;

@Autowired
public WizardService(WizardFactoryService wizardFactoryService) {
this.wizardFactoryService = wizardFactoryService;
}

@Override
public ResponseEntity<WizardScreenDTO> postWizard(WizardRequestDTO wizardRequestDTO) {

IWizardScreenService wizardScreenService = wizardFactoryService.getScreenWizard(wizardRequestDTO.getSceenEnum());

if(wizardRequestDTO.getRequestTypeEnum().getRequestType().equals(WizardScreenRequestTypeEnum.CREATE.getRequestType()))
{
/**
* create
*/


WizardScreenDTO createdDTO = wizardScreenService.createModelWizard(wizardRequestDTO.getWizardScreenDTO());
return new ResponseEntity<>(createdDTO, HttpStatus.CREATED);
}
else if(wizardRequestDTO.getRequestTypeEnum().getRequestType().equals(WizardScreenRequestTypeEnum.UPDATE.getRequestType()))
{
/**
* update
*/

WizardScreenDTO updatedDTO = wizardScreenService.updateModelWizard(wizardRequestDTO.getWizardScreenDTO());
return new ResponseEntity<>(updatedDTO, HttpStatus.OK);
}

return new ResponseEntity<>(new WizardScreenDTO(), HttpStatus.NOT_ACCEPTABLE);
}

@Override
public ResponseEntity<WizardScreenDTO> getWizard(Long id, WizardSceenEnum wizardSceenEnum) {

if(Objects.nonNull(id))
{
IWizardScreenService wizardScreenService = wizardFactoryService.getScreenWizard(wizardSceenEnum);
WizardScreenDTO wizardScreenDTO = wizardScreenService.getWizard(id);

return new ResponseEntity<>(wizardScreenDTO,HttpStatus.OK);
}
return new ResponseEntity<>(new WizardScreenDTO(), HttpStatus.BAD_REQUEST);
}
}

Methodlarımızın içine baktığımızda dikkat edilecek satır :

IWizardScreenService wizardScreenService =  wizardFactoryService.getScreenWizard(wizardRequestDTO.getSceenEnum());

factory class ımız getScreenWizard methodundaki aldığı enum parametresine göre bize aslında IWizardScreenService olarak ilgili ekranı yöneten class ımızı dönüyor.

Örnek olarak;

  • enum değeri : PRODUCT_INFO_SCREEN return eden class : ProductInfoScreenService
  • enum deperi : PRODUCT_COMPANY_SCREEN return eden class : ProductCompanyScreenService

Bu aşamadan sonra getWizard(), createModelWizard(), updateModelWizard() call ettiğimizde return eden class ın ilgili methodlarındaki logic işletilecektir.

En son olarak da Controller class ımızı yazabiliriz :

WizardScreenController

@RestController
@RequestMapping("wizard-controller")
public class WizardScreenController {

private final IWizardService wizardService;

@Autowired
public WizardScreenController(IWizardService wizardService) {
this.wizardService = wizardService;
}

@GetMapping("/getWizard")
public ResponseEntity<WizardScreenDTO> getWizard(@RequestParam Long id, @RequestParam WizardSceenEnum wizardSceenEnum)
{
return wizardService.getWizard(id,wizardSceenEnum);
}

@PostMapping(value = "postWizard")
public ResponseEntity<WizardScreenDTO> postWizard(@RequestBody WizardRequestDTO wizardRequestDTO)
{
return wizardService.postWizard(wizardRequestDTO);
}

}

Bu class da 2 tane endpoint yer almaktadır.

  • getWizard enpoint : Long olarak Product objesinin id bilgisini ve hangi ekran yönetilecekse onunla ilgili enum bilgisini almaktadır.
  • postWizard endpoint : WizardRequestDTO tipinde içinde diğer ekranların da yönetilmesini sağlayan DTO ları içeren wrap DTO parametresi almaktadır. Bu wrap DTO içinde hangi ekran yönetileceği ile ilgili ekran enum değeri ve yapılacak işlem ne ise (CREATE,UPDATE) ile ilgili requestType tipinde enum değeri bulunmaktadır.

Her iki endpoint de WizardScreenDTO objesi dönmektedir. Bu wrap DTO içinde de istersek tüm DTO ları istersek bize lazım olan DTO nesneleri bulunmaktadır.

En son olarak Postman de 2 endpoint için de istek atarsak :

Get isteği

Post isteği

Uzun bir yazı oldu. Süreci anlatmak için logic kısmını biraz basit tuttum.

Umarım faydalı olabilmişimdir.

Github code: https://github.com/serdaralkancode/spring-wizard-strategy-pattern

Okuduğunuz için teşekkür ederim

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Serdar A.
Serdar A.

Written by Serdar A.

Senior Software Developer & Architect at Havelsan Github: https://github.com/serdaralkancode #Java & #Spring & #BigData & #React & #Microservice

No responses yet

Write a response