Ana içeriğe geç

1. Eksen#

EKSEN ismini verdiğimiz yazılım geliştirme altyapısı; mikro servis mimari prensiplerinden, modülerlik, sürekli otomasyon, gizli uygulama erişimi, merkezileştirmekten kaçınmak, bağımsız kurulum, hata durumlarının yönetimi, gözlenebilirlik ile ilgili entegre çözümler barındırmaktadır.

EKSEN, Tüm Kamu Kurum ve Kuruluşlarımızın yabancı ürünlere ödediği lisans maliyetlerinin sıfırlanması ve yurtdışı bağımlılıklarımızın yok edilmesi hedeflenerek, geniş kabul gören, olgunluğunu ispatlayarak defacto haline gelmiş açık kaynak kodlu yazılımları kullanarak geliştirmiş olduğumuz yazılım geliştirme altyapısıdır.

Genel İçerigi#

  • Yerli ve milli yazılım vizyonu ile açık kaynak(open source) teknolojiler kullanılarak geliştirilmiştir.
  • Programlama dili olarak Java dilinin güncel versiyonu kullanılmaktadır.
  • Java uygulaması geliştirmek için Spring Boot Framework kullanılmaktadır.
  • Mikro servis mimariye uygun uygulama geliştirmeler için Spring Cloud Framework kullanılmaktadır.
  • Java dili ile geliştirme yapıldığında kullanılan popüler açık kaynak farklı kütüphaneler de kullanılmaktadır. (apache, querydsl, mapstruct vb.)
  • Kendi teknoloji havuzumuzla entegre çalışması için özelleştirilmiş katmanlar(servis ve model contributer) eklenmiştir.
  • Güvenlik mimarisi olarak OAuth standartları uygulanmaktadır.
  • Veri tabanı işlemleri için JPA ve QueryDSL kullanılmaktadır.
  • Cache ve veri tarihçesi gibi işlemler için altlıklar sağlanmaktadır.

Projelerin ortak yanları olan ve genelde en fazla kaynak harcanan parçaları olan altyapı bileşenleri her proje için tekrar geliştirilmekte ve test edilmektedir. Ekibimizin bir diğer ana görevi altyapı bileşenlerini küçük ve büyük proje farkı gözetmeksizin geliştirip test edilmiş güvenli bir altyapı hizmeti sunmaktır.

Kullanılan açık kaynak teknolojilerin yeni versiyonlarına hızlı bir şekilde geçiş yapılabilecek bir yapı sunulmaktadır. Aynı zamanda yeni çıkan açık kaynak yapılar incelenerek hızlı bir şekilde altyapımıza entegre edilmektedir.

Genel Yapı Ve Paketler#

Framework instance projelerinin genel yapısı hakkında detaylı bilgi Genel Yapı ve Paketler sayfasında verilmiştir.

Sağlanan Başlıca Anotasyonlar#

Genel Bileşenler#

Framework#

Uygulama geliştirilirken başta Spring olmak üzere third-party temel bileşenleri gereksinimlere göre özelleştirilmiş olarak hizmete sunan altyapı bileşenidir. Actuator, configuration, context, crypto, exception, initializer, service, swagger, util gibi temel bileşenleri içermektedir. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.


Actuator#

import tr.com.havelsan.javarch.actuator.annotation.HvlActuatorService;

@HvlActuatorService(name = "hvlBpmnIntegrationRestService", groupName = "hvlBpmnIntegration")

Uygulamada rest uçların ve modellerin bilgilerinin dönülmesini sağlamaktadır. Bu bilgileri alabilmek için ilk olarak ip:port/actuator adresine istek atılmalıdır.

Servis bilgilerinin alınabilmesi için aşağıdaki uçların kullanılması gerekmektedir.

Service Endpoints

Model bilgilerinin alınabilmesi için aşağıdaki uçların kullanılması gerekmektedir.

Model Endpoints

TS-Generator ürünümüz type-script sınıflarını üretmek için yukaridaki uçları kullanmaktadır. Java temel annotation, model ve servis sınıflarının type-script'i üretilmektedir.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-management.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-actuator'

Configuration#

import tr.com.havelsan.javarch.configuration.HvlBaseConfiguration;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Configuration extends HvlBaseConfiguration {

}

Temel konfigurasyon sınıfı sunulmaktadır. Bu sınıftan türeyen sınıflar context'e dahil edildiğinde log atılmaktadır. Aynı zamanda tarama işlemlerinde sadece konfigurasyon taranması için ayraç olarak kullanılabilmektedir.

Profile bağlı tarama yapabilmek için sağlanan HvlProfileComponentScanFilter sınıfı bulunmaktadır. Bu sınıf kullanılarak sadece @Profile içeren konfigürasyon sınıfları taranabilmektedir.

@Configuration
@ComponentScan(basePackages = {HvlLogServerConfigurationConstant.BASE_PACKAGE},
        useDefaultFilters = false,
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, value = HvlProfileComponentScanFilter.class),
        }
)
public class HvlLogServerConfiguration extends HvlBaseConfiguration {
}

Yaml veya properties dosyalarından konfigurasyonlarını ayrıştırmak için HvlPropertyParser sınıfı kullanılmaktadır. Bu sınıf sayesinde iç içe konfigurasyon verilmesi sağlanmaktadır.

service:
  url: ${service.url:${default.url}}


Konfigurasyonları jasypt kütüphanesi ile şifreleme yeteneği bulunmaktadır. Şifreleme yeteneği sağlanan algoritma türleri: HvlConfigurationEncryptorType

  • PBES
  • STANDART_PBES
  • POOLED_PBES
  • ASYMETRIC

NOT: Şifreleme işlemi StringEncryptor ile yapılmaktadır. Jasypt standartları ile şifreleme işlemi yapmak isterseniz StringEncryptor sınıfı kullanılabilir.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-instance.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-configuration'
    group: 'tr.com.havelsan.framework', name: 'hvl-configuration-encryptor'


Context#

Uygulama içeriğinde Bean, Environment ve System enviroment'a ulaşmayı sağlamaktadır.

2 şekilde kullanılabilmektedir:

  • DI (Dependency Injection) ile kullanılabilir.
import org.springframework.stereotype.Component;
import tr.com.havelsan.javarch.context.HvlApplicationContext;

@Component
public class SampleService {

    private final HvlApplicationContext applicationContext;

    public SampleService(HvlApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void test() {
        applicationContext.getBean(SampleService.class);
        applicationContext.getEnvironment();
        applicationContext.getSystemLocale();
    }

}
  • Bean olmayan sınıflar statik olarak Holder üzerinden kullanılabilir.
import tr.com.havelsan.javarch.context.holder.HvlApplicationContextHolder;

import java.util.Objects;

public final class SampleService {

    public static SampleService INSTANCE;

    public static SampleService getInstance() {
        if (Objects.isNull(INSTANCE)) {
            INSTANCE = new SampleService();
        }
        return INSTANCE;
    }

    public static void test() {
        HvlApplicationContextHolder.getBean(SampleService.class);
        HvlApplicationContextHolder.getEnvironment();
        HvlApplicationContextHolder.getSystemLocale();
    }
}

Uygulama içerisinde Bean'ler arası event mekanizmasına destek sağlamaktadır. Bunun için HvlApplicationEventListener ve HvlApplicationEventPublisher sınıfları kullanılmaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-context.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-context'


Crypto#

Uygulamada şifreleme işlemlerinde kullanılmaktadır. (Örneğin veritabanı kolonlarında şifreleme vb.) Güncel sürümde AES destek verilmektedir.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.context.holder.HvlApplicationContextHolder;
import tr.com.havelsan.javarch.crypto.data.HvlCryptoType;
import tr.com.havelsan.javarch.crypto.service.HvlCryptoServiceBuilder;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlSampleApplication {


    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlSampleApplication.class}, args);

        final HvlCryptoService aesCryptoService =
                HvlCryptoServiceBuilder.create(HvlCryptoType.AES).setKey("mySecretKey").build();
        final String encryptText = aesCryptoService.encrypt("test");
        final String decryptText = aesCryptoService.decrypt(encryptText);
    }
}

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-crypto'


Exception#

Altyapıdan checked ve unchecked exception kullanımı sağlanmaktadır. Bu sınıflar HvlCheckedException ve HvlUncheckedException sınıflarıdır.

Exception sınıfları içerisinde HvlErrorDetail nesnesi bulunmaktadır. Bir isteğin yaşam döngüsü boyunca hata alması durumunda HvlErrorDetail alanı vasıtası ile bilgi dönülmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-exception'


Initializer#

Uygulamaya ilklendirme özelliği kazandırmaktadır. İlklendirme belirli bir path üzerindeki script dosyaları ile yapılabildiği gibi aynı zamanda git üzerinden de script dosyalarını okuyup ilklendirme yapılabilmeyi sağlamaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-data.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-initializer'

Bağımlılık eklendikten sonra git ilklendirmesi için HvlInitializerGitProperties sınıfından extend edip propertyler bağlanarak kullanıma hazır hale getirilebilir.

@ConfigurationProperties(prefix = HvlEnableRToolConfigurationConstant.REPORT_INITIALIZER_PROPERTIES_PREFIX)
public class HvlRToolReportInitializerGitProperties extends HvlInitializerGitProperties {
}

Git kullanmadan yalnızca path üzerinden ilklendirme özelliği kazandırılmak isteniyorsa aşağıdaki örnekteki gibi HvlInitializerProperties sınıfı exten edilip propertyler bağlanabilir.

@ConfigurationProperties(prefix = HvlEnableRToolConfigurationConstant.REPORT_INITIALIZER_PROPERTIES_PREFIX)
public class HvlRToolReportInitializerProperties extends HvlInitializerProperties {
}

Sonrasında aşağıdaki gibi HvlInitializerGitServiceImpl sınıfından extend eden bir ilklendirme komponenti ile ilklendirme süreci tamamlanabilir.

@Component
@ConditionalOnProperty(
        prefix = HvlEnableRToolConfigurationConstant.REPORT_INITIALIZER_PROPERTIES_PREFIX,
        name = HvlRToolReportInitializerProperties.ENABLED_PROPERTY_NAME,
        havingValue = BooleanUtils.TRUE
)
public class HvlRToolReportInitializer
        extends HvlInitializerGitServiceImpl implements InitializingBean {

    private final HvlRToolReportInitializerProperties reportInitializerProperties;

    private final HvlRToolBatchedReportImportProcessor batchedReportImportProcessor;

    public HvlRToolReportInitializer(
            HvlRToolReportInitializerGitProperties reportInitializerGitProperties,
            HvlRToolReportInitializerProperties reportInitializerProperties,
            HvlRToolBatchedReportImportProcessor batchedReportImportProcessor) {
        super(reportInitializerGitProperties);
        this.reportInitializerProperties = reportInitializerProperties;
        this.batchedReportImportProcessor = batchedReportImportProcessor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        initialize();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void doInit(String path) {
        final Path batchedReportImportFilePath = Path.of(path)
                .resolve(this.reportInitializerProperties.getBatchedReportImportFilePath());
        batchedReportImportProcessor.importReportTemplatesFrom(batchedReportImportFilePath)
                .block();
    }
}


Service#

Uygulamadan dışarıya açılan servis uçları (Rest Controller) buradan konfigure edilmektedir. (Örneğin serialization kuralları, gzip, cors, cookie vb.)

HvlHttpHeader sınıfında altyapının isteklerde (Http request) ve cevaplarda (Http response) kullandığı özel 'header' alanları bulunmaktadır.

Uygulamada istekle (Http request) ilgili bilgilere anlık ulaşabilmek için HvlServiceContext ve HvlServiceContextHolder sınıfları bulunmaktadır.

HvlServiceContextHolder kullanım örneği:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.service.context.holder.HvlServiceContextHolder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlSampleApplication.class}, args);

        final HttpServletRequest servletRequest = HvlServiceContextHolder.getServletRequest();
        final HttpServletResponse servletResponse = HvlServiceContextHolder.getServletResponse();
    }

}

HvlServiceContext kullanım örneği:

import org.springframework.stereotype.Service;
import tr.com.havelsan.javarch.service.context.HvlServiceContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class SampleService {

    private final HvlServiceContext serviceContext;

    public SampleService(HvlServiceContext serviceContext) {
        this.serviceContext = serviceContext;
    }

    public void test() {
        final HttpServletRequest servletRequest = serviceContext.getServletRequest();
        final HttpServletResponse servletResponse = serviceContext.getServletResponse();
    }

}

Uygulamadan dışarıya açılan servis uçlarının (Rest Controller) döneceği verileri standartlaştırmak için HvlResponse ve HvlResponseEntity sınıfları bulunmaktadır. Bu sınıflar sayesinde payload, header, errorDetail gibi alanlar istemciye standart olarak dönülmektedir. HvlResponseEntity objelerin byte array gibi yapılarda geriye dönülmesinin istendiği durumlarda kullanılmaktadır.

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tr.com.havelsan.javarch.service.data.HvlResponse;
import tr.com.havelsan.javarch.service.data.HvlResponseEntity;

@RestController
@RequestMapping("/sample")
public class SampleController {

    @GetMapping(path = "/response", produces = MediaType.APPLICATION_JSON_VALUE)
    public HvlResponse<String> response() {
        return new HvlResponse<>("Response sample");
    }

    @GetMapping(path = "/response-entity", produces = MediaType.APPLICATION_JSON_VALUE)
    public HvlResponseEntity<String> responseEntıty() {
        return new HvlResponseEntity<>("Response entity sample");
    }

}

Uygulamadan dışarıya açılan servis uçlarının (Rest Controller) hata fırlatması (throw) durumunda hataya özgü HttpStatus bilgisini cevaba (Http response) eklemeyi sağlayan yapı bulunmaktadır. Bu yetenek @HvlExceptionHttpStatus anotasyonu ile sağlanmaktadır.

import org.springframework.http.HttpStatus;
import tr.com.havelsan.javarch.exception.HvlCheckedException;
import tr.com.havelsan.javarch.exception.model.HvlErrorDetail;
import tr.com.havelsan.javarch.service.annotation.HvlExceptionHttpStatus;

@HvlExceptionHttpStatus(code = HttpStatus.BAD_REQUEST)
public class SampleInvalidRequestException extends HvlCheckedException {

    public static final String ERROR_CODE = "code";

    public static final String ERROR_MESSAGE = "message";

    public SampleInvalidRequestException() {
        super(ERROR_MESSAGE, new HvlErrorDetail(ERROR_CODE, ERROR_MESSAGE));
    }

    public SampleInvalidRequestException(HvlErrorDetail errorDetail) {
        super(errorDetail);
    }

}

HvlRestExceptionHandler sınıfı ile sistemde handle edilen veya edilmeyen hatalar filtrelenip gerekli standartlara göre istemciye dönülmektedir. (HvlResponse ve HvlResponseEntity olarak) Burada geliştirici tarafında yutulan hatalar ele alınmamaktadır.

HvlCookieUtil sınıfı ile 'cookie' ile ilgili hizmetler sunulmaktadır. Örnek kullanım:

import org.springframework.stereotype.Service;
import tr.com.havelsan.javarch.service.configuration.properties.HvlCookieProperties;
import tr.com.havelsan.javarch.service.context.HvlServiceContext;
import tr.com.havelsan.javarch.service.util.HvlCookieUtil;

@Service
public class SampleService {

    private final HvlServiceContext serviceContext;

    public SampleService(HvlServiceContext serviceContext) {
        this.serviceContext = serviceContext;
    }

    public void test() {
        HvlCookieUtil.addCookie(serviceContext.getServletResponse(),
                "cookieName",
                "cookieValue",
                new HvlCookieProperties());
    }

}

ÖNERİ: Bean kullanımlarında servis arayüz sınıflarında @Validated ve @Valid annotationları kullanılmalıdır. Arayüz içerisindeki metotlara da gerekli validasyon annotationları konulmalıdır. Böylece metot içerisindeki iş mantığı çalışmadan ve kaynak tüketmeden önce validasyondan geri döner.

import org.springframework.validation.annotation.Validated;
import tr.com.havelsan.javarch.data.commons.pageable.HvlPage;
import tr.com.havelsan.javarch.samples.jpa.data.entity.HvlJpaSample;
import tr.com.havelsan.javarch.samples.jpa.data.model.HvlJpaSampleModel;
import tr.com.havelsan.javarch.samples.jpa.data.model.query.HvlJpaSampleQueryModel;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.util.List;

@Validated
public interface HvlSampleService {

    HvlJpaSampleModel save(@Valid @NotNull HvlJpaSampleModel sampleModel);

    HvlJpaSampleModel update(@Valid @NotNull HvlJpaSampleModel sampleModel);

    void deleteById(@NotNull @Positive Long id);

    List<HvlJpaSampleModel> getList();

    List<HvlJpaSampleModel> queryList(HvlJpaSampleQueryModel sampleQueryModel);

    List<HvlJpaSampleModel> queryList(HvlJpaSampleQueryModel queryModel, String locale);

    HvlPage<HvlJpaSampleModel> queryPage(HvlJpaSampleQueryModel sampleQueryModel);

    List<HvlJpaSample> getAllSample();

    void saveAll();

    void updateAll();

    void deleteAll(List<HvlJpaSample> entities);
}

drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-service.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-service'


Swagger#

Uygulamaya swagger yeteneği kazandırmak için kullanılmaktadır. Cloud ve Boot için destek sağlanmaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-swagger.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-swagger'


Util#

Uygulama geliştirirken genel destek sınıfları sunulmaktadır. Destek sınıfları:

  • Dil ve ortak kullanılacak sabitler için HvlCommonConstant, HvlLanguageConstant
  • Sertifika işlemleri için HvlCertificateUtil
  • Cron işlemleri için HvlCronUtil
  • IP ayrıştırma işlemleri için HvlIPUtil
  • String işlemleri için HvlStringUtil

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-util'


Cloud Framework#

Uygulamaları cloud yapısına uygun şekilde geliştirmek için hizmete sunulan altyapı bileşenidir. Temel teknoloji bileşenleri olarak OpenFeign, Spring Cloud kullanılmaktadır. Exception handling, tracing, registry integration vb. bileşenleri içermektedir. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.


Configuration#

Mikro servis mimaride çok sayıda uygulama dağıtık mimaride bulunmaktadır. Bu durum uygulamalar ayağa kalkarken gerekli konfigurasyonu nasıl vereceğimiz problemini doğurmaktadır. EKSEN; config-server entegrasyonu ile konfigurasyonlar için tek kaynaktan beslenme sağlamaktadır.

config-server kullanılırken dikkat edilmesi gereken konular bulunmaktadır. Bunlar;

  • config-server üzerinden gelen özellikler ve dosyalar baskınlık göstermektedir. Uygulamada resources altında bulunan .yml uzantılı dosyalar ve içerisindeki özellikler eğer config-server üzerinden gelmiyorsa kullanılabilir. Aksi takdirde **config-server**dan gelen ezecektir.
  • Uygulama ayağa kaldırılırken enviroment olarak verilen özellikler config-server üzerinden gelen özellikleri ezmektedir.
  • config-server üzerinden override edilmiş özellikler herhangi bir şekilde ezilemez. Özelliğin her uygulama için aynı olması isteniyorsa bu kullanım tavsiye edilmektedir. Bu yeteneğin kullanılması için config-server ayağa kaldırılırken environment'ların önüne 'SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_' ön ekinin eklenmesi gerekmektedir. Örnek:
version: '2.1'

services:
  config-server-service:
    .
    .
    environment:
      SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_HVL_OAUTH_SESSION_SERVICE_URL: http://hvlsessionserver:9080
      SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_HVL_OAUTH_SESSION_SERVICE_PATH: /

Uygulamalarda config-server bağlantısı bootstrap.yml üzerinden sağlanmaktadır.

spring:
  config:
    import:
      - optional:configserver:${spring.cloud.config.uri}
  cloud:
    config:
      uri: ${SERVER_CONFIGURATION_REMOTE_URL:http://localhost:8888/config}
      profile: ${SERVER_CONFIGURATION_CLOUD_PROFILE:cloud-eureka,cloud-sleuth,hvl-context,hvl-data,hvl-logger,hvl-mail,hvl-security,hvl-service,hvl-session,database-datasource,instance,kafka,management,swagger,apm}
      label: ${SERVER_CONFIGURATION_LABEL:framework(_)spring}
      enabled: ${SERVER_CONFIGURATION_REMOTE_ENABLED:true}
      username: ${CONFIG_AUTH_USERNAME:admin}
      password: ${CONFIG_AUTH_PASSWORD:123456}

  logging:
    auth:
      username: ${LOGGING_AUTH_USERNAME:${spring.cloud.config.username}}
      password: ${LOGGING_AUTH_PASSWORD:${spring.cloud.config.password}}
    config: ${LOGGING_CONFIG:${spring.cloud.config.uri}/${spring.application.name}/default/framework(_)log4j2(_)instance(_)oauth/log4j2.yml}

EKSEN olarak loglama ve genel bütün konfigürasyonları config-server üzerinden almaktayız. Burada profile mantığı kullanılarak parçalama yapılmıştır. Konfigürasyon dosyalarını ve config-server dosyalarını hvl-infra adresinden inceleyebilirsiniz.


Eureka Web Starter#

Mikro servis mimaride dağıtık servisler hakkında bilgi almak için service-registry olarak Eureka kullanılmasına destek sağlamaktadır. Eureka entegrasyonu için gerekli temel yapıları sağlamaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-cloud-eureka.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cloud', name: 'hvl-cloud-eureka-web-starter'


Kubernetes Web Starter#

Mikro servis mimaride dağıtık servisler hakkında bilgi almak için service-registry olarak Kubernetes kullanılmasına destek sağlamaktadır. Kubernetes entegrasyonu için gerekli temel yapıları sağlamaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-cloud-kubernetes.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cloud', name: 'hvl-cloud-kubernetes-web-starter'


Service#

Mikro servis yapılarda uygulamaların birbirlerine declarative yapıda istek (Http request) atabilmesini sağlamaktadır. Yani geliştirici istek atacağı interface'i tanımladıktan sonra java üzerinden implementasyon yapmadan istek atabilmektedir. Burada teknoloji olarak OpenFeign kullanılmaktadır.

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name = "", url = "", path = "")
public interface SampleRestService {

    @GetMapping(path = "/sample", produces = MediaType.APPLICATION_JSON_VALUE)
    String sample();
}

Declarative yapıları injection yapmadan oluşturmak için HvlFeignClientBuilder sınıfını kullanılabilir.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.cloud.service.builder.HvlFeignClientBuilder;
import tr.com.havelsan.javarch.samples.jpa.data.logic.SampleRestService;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlSampleApplication.class}, args);

        final SampleRestService sampleRestService = HvlFeignClientBuilder.create().target(SampleRestService.class);

    }

}

FeignClient sınıflarının decoder, encoder, interceptor, logger alanlarını da konfigure edebilirsiniz.

EKSEN, decoder işlemi için HvlDecoder interface'inden türeyen HvlFeignClientDecoder, HvlFeignClientErrorDecoder, HvlFeignResponseDecoder sınıfları ile destek sağlamaktadır.

EKSEN, encoder işlemi için HvlFeignEncoder sınıfı ile destek sağlamaktadır.

EKSEN, interceptor işlemi için HvlCloudServiceRequestInterceptor sınıfı ile destek sağlamaktadır.

EKSEN, logger işlemi için HvlFeignClientLogger sınıfı ile destek sağlamaktadır.

NOT: Yukarıda sağlanan desteklerin kullanımı zorunlu değildir. Uygulamaya göre özelleştirilebilir hatta arttırılabilir. FeignClient özelinde bile yazılabilir. Fakat burada özelleştirme yapılırken altyapının sağladığı destekler incelenmeli ve isteğin yaşam döngüsü bozulmamalıdır.

Http isteği için FeignClient declarative yapısının kullanılmasının en büyük problemi, mikro servis mimaride uygulamalar dağıtık mimaride farklı JVM de çalıştığı için hatanın ele alınmasıdır.

EKSEN, FeignClient kullanımında istek sonucunda hatayı JVM'de ele alınmasını sağlanmıştır. Bunun için FeignClient uçlarında kullanılacak hataların @HvlFeignClientError annotation'ı ile işaretlenmesi gerekmektedir.

EKSEN, Feign client uçları için @HvlPrivateFeignRestService ve @HvlPublicFeignRestService sağlamaktadır. Bu uçların şuan için bir işlevi yoktur ancak dışarıya açılmak istenen uçlar ve gizli kalması istenen uçların kod okunaklılığı açısından bu anotasyonlarla işaretlenmesi önerilir.

import org.springframework.http.HttpStatus;
import tr.com.havelsan.javarch.cloud.service.annotation.HvlFeignClientError;
import tr.com.havelsan.javarch.exception.HvlCheckedException;
import tr.com.havelsan.javarch.exception.model.HvlErrorDetail;
import tr.com.havelsan.javarch.service.annotation.HvlExceptionHttpStatus;

@HvlFeignClientError
@HvlExceptionHttpStatus(code = HttpStatus.BAD_REQUEST)
public class SampleInvalidRequestException extends HvlCheckedException {

    public static final String ERROR_CODE = "code";

    public static final String ERROR_MESSAGE = "message";

    public SampleInvalidRequestException() {
        super(ERROR_MESSAGE, new HvlErrorDetail(ERROR_CODE, ERROR_MESSAGE));
    }

    public SampleInvalidRequestException(HvlErrorDetail errorDetail) {
        super(errorDetail);
    }

}

NOT: FeignClient hatalarının sistem tarafından taranması gerekmektedir. hvl.core.service.cloud.feign.client.exception.scan-path özelliğine hatanın bulunduğu package verilmesi gerekmektedir.

ÖNERİ: FeignClient kullanımlarında arayüz sınıflarında @Validated ve @Valid annotationları kullanılmalıdır. Arayüz içerisindeki metotlarada gerekli validasyon annotationları konulmalıdır. Böylece istek atılmadan validasyondan geri döner.

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;

import javax.validation.constraints.NotEmpty;

@FeignClient(name = "", url = "", path = "")
@Validated
public interface SampleRestService {

    @GetMapping(path = "/sample", produces = MediaType.APPLICATION_JSON_VALUE)
    String sample(@NotEmpty String plainText);

}

drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-service.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cloud', name: 'hvl-cloud-service'


Session#

Uygulama içerisinde istek yaşam döngüsünde session bilgisinin taşınmasını ve kullanılmasını sağlayan altyapı bileşenidir. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.


Context#

Uygulamada isteğin yaşam döngüsü boyunca Session bilgisi burada tutulmaktadır. HvlSession sınıfı ile tutulmaktadır.

İki şekilde kullanılabilmektedir:

  • DI (Dependency Injection) ile kullanılabilir.
import org.springframework.stereotype.Service;
import tr.com.havelsan.javarch.session.common.model.HvlSession;
import tr.com.havelsan.javarch.session.context.HvlSessionContext;

@Service
public class SampleService {

    private final HvlSessionContext sessionContext;

    public SampleService(HvlSessionContext sessionContext) {
        this.sessionContext = sessionContext;
    }

    public void test() {
        final HvlSession session = sessionContext.currentSession();
    }

}
  • Bean olmayan sınıflar statik olarak 'Holder' üzerinden kullanılabilir.
import tr.com.havelsan.javarch.session.common.model.HvlSession;
import tr.com.havelsan.javarch.session.context.HvlSessionContextHolder;

import java.util.Objects;

public final class SampleService {

    public static SampleService INSTANCE;

    public static SampleService getInstance() {
        if (Objects.isNull(INSTANCE)) {
            INSTANCE = new SampleService();
        }
        return INSTANCE;
    }

    public static void test() {
        final HvlSession session = HvlSessionContextHolder.currentSession();
    }

}

Uygulamada header ve cookie'den alınan bilgiler HvlSessionContextFilter sınıfında ayrıştırılarak HvlSession sınıfı ile session bilgisi tutulmaktadır.

NOT: HvlSession sınıfı içerisinde attributeMap alanı bulunmaktadır. Yani istenildiği zaman bu alan kullanılarak session genişletilebilir.

Session genişletilmesinin 2 yöntemi bulunmaktadır: * HvlSessionContextManagerImpl sınıfı extend edilerek değiştirilmek istenen metotlar değiştirilebilir. * HvlSessionContextFilter filtesi yerine uygulamaya özgü filtre yazılabilir. Bu filtre sonrasında çalıştırılarak attributeMap alanına ekleme yapılabilir.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-session.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework', name: 'hvl-session-context'


Security#

Uygulama içerisinde istek yaşam döngüsünde güvenlik ile ilgili bilgilerin taşınmasını ve kontrolünün yapılmasını sağlayan altyapı bileşenidir. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.

ÖNERİ: @PreAuthorize gibi annotationlar'ın RestController üzerine konulması tavsiye edilmektedir. Servise yetkisi olan kişi RestController'dan geçtikten sonra güvenliğe takılmamalıdır. Karmaşık yetki havuzlarının oluşmasını önlemektedir.

@RestController
@RequestMapping("${hvl.system.service.menu-item.controller-path:/menu}")
public class HvlMenuItemRestController implements HvlMenuItemOperationalRestService, HvlMenuItemRestService {

    private final HvlMenuItemService menuItemService;

    /**
     * Instantiates a new HvlMenuItemRestController.
     *
     * @param menuItemService the menu item service
     */
    public HvlMenuItemRestController(HvlMenuItemService menuItemService) {
        this.menuItemService = menuItemService;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @PreAuthorize("hasAuthority('keysys')")
    public HvlResponse<Void> save(@NotNull @Valid @RequestBody HvlMenuItemModel menuItemModel) {
        menuItemService.save(menuItemModel);
        return new HvlResponse<>();
    }
}


JWT#

CSRF (Cross Site Request Forgery) saldırılarını önlemek amacı ile kullanılmaktadır. Yani dışarıdan gelen isteklerin authentication (kimlik doğrulama) kısmından geçmiş olduğunu teyit etmek içindir. EKSEN, authentication ile ilgili verileri HVL_SESSION_ID ve HVL_TOKEN alanları ile taşımaktadır. (Daha detaylı bilgi için: https://jwt.io/)

NOT: HVL_TOKEN değişkeni application-hvl-security.yml alanı içerisinde hvl.core.security.jwt.header.token alanından değiştirilebilir. Değiştirilmesi durumunda alana bağlı durumlar da düzenlenmelidir.

JWT üretmek için HvlJwtGeneratorBuilder sınıfı kullanılmaktadır. JWT üretirken şifreleme imzası (signature) önem taşımaktadır. HvlJwtAlgorithm sınıfı ile şifreleme algoritması seçilmektedir.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.jwt.generator.builder.HvlJwtGeneratorBuilder;
import tr.com.havelsan.javarch.jwt.parser.algorithm.HvlRS256Algorithm;
import tr.com.havelsan.javarch.jwt.parser.model.HvlRSKeyPair;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlJpaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlJpaServerApplication.class}, args);

        HvlJwtGeneratorBuilder.create()
                .setAlgorithm(new HvlRS256Algorithm(new HvlRSKeyPair()))
                .build();
    }

}

JWT içerisine konulan bilgiyi ayrıştırmak (parse) için HvlJwtParserBuilder sınıfı kullanılmaktadır. Burada önemli olan üretim yapılan algoritma ile ayrıştırma yapılan algoritmanın türünün aynı olması gerekmektedir. (HvlJwtAlgorithm aynı olmalıdır.)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.jwt.parser.algorithm.HvlRS256Algorithm;
import tr.com.havelsan.javarch.jwt.parser.builder.HvlJwtParserBuilder;
import tr.com.havelsan.javarch.jwt.parser.model.HvlRSKeyPair;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlJpaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlJpaServerApplication.class}, args);

        HvlJwtParserBuilder.create()
                .setAlgorithm(new HvlRS256Algorithm(new HvlRSKeyPair()))
                .build();
    }

}

NOT: EKSEN, JWT üretimi için varsayılan olarak HvlRS256Algorithm (hvl.core.security.jwt.key-provider.algorithm) algoritması kullanmaktadır. RSA algoritmasının kullanılabilmesi için private ve public key olması gerekmektedir.

EKSEN'de varsayılan olarak hvl.pem ve hvl.public.pem dosyaları bulunmaktadır. Bu dosyalar hvl.core.security.jwt.key-provider.file.public-file-path ve hvl.core.security.jwt.key-provider.file.private-file-path alanları ile değiştirilebilmektedir.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-security.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.security', name: 'hvl-jwt-generator'
    group: 'tr.com.havelsan.framework.security', name: 'hvl-jwt-parser'
    group: 'tr.com.havelsan.framework.security', name: 'hvl-jwt-security'


Session Provider#

Sisteme giriş yapmış (authenticated) bir istemcinin her bir isteğinde herhangi bir uygulama (Örneğin session-server) ile kimlik doğrulaması yapabileceği arayüz sunulmaktadır. HvlSecuritySessionProvider sınıfı implement edilerek oturum veya istek bilgileri güvenlik katmanına özelleştirilerek aktarılabilir.

NOT: Mikro servis mimarilerde uygulamalar stateless olduğu için sisteme giriş yapan kullanıcıların oturum bilgileri bir sistemde tutulması gerekmektedir. HvlSecuritySessionProvider sınıfı implement edilerek herhangi bir uygulama ile entegre olunabilir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.security', name: 'hvl-security-session-provider'


Context#

Uygulama güvenlik ile ilgili verilere ulaşmamızı sağlamaktadır.

İki şekilde kullanılabilmektedir:

  • DI (Dependency Injection) ile kullanılabilir.
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import tr.com.havelsan.javarch.security.common.model.HvlAuthenticationToken;
import tr.com.havelsan.javarch.security.context.HvlSecurityContext;

import java.util.Collection;

@Service
public class SampleService {

    private final HvlSecurityContext securityContext;

    public SampleService(HvlSecurityContext securityContext) {
        this.securityContext = securityContext;
    }

    public void test() {
        final HvlAuthenticationToken authentication = securityContext.getAuthentication();
        final Collection<GrantedAuthority> authorities = authentication.getAuthorities();
    }

}
  • Bean olmayan sınıflar statik olarak 'Holder' üzerinden kullanılabilir.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tr.com.havelsan.javarch.security.common.model.HvlAuthenticationToken;
import tr.com.havelsan.javarch.security.context.HvlSecurityContextHolder;

/**
 * @author javarch
 */
@SpringBootApplication
public class HvlJpaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(new Class[]{HvlJpaServerApplication.class}, args);

        final HvlAuthenticationToken authentication = HvlSecurityContextHolder.getAuthentication();
    }

}

NOT: Hiyerarşik yetki desteği sağlanmaktadır. Yetki Ekleme sayfasından detaylı bilgi edinilebilir.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-security.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.security', name: 'hvl-security-context'


Web Starter#

EKSEN thymeleaf ile geliştirilen giriş ekranını sağlamaktadır. Uygulamalarda kullanılarak login işlemi gerçekleştirilebilir.

@Bean
@ConditionalOnMissingBean
AuthenticationProvider authenticationProvider(HvlWebSecurityProperties webSecurityProperties){
        return new HvlWebSecurityInmemoryAuthenticationProvider(webSecurityProperties);
}

Sağlanan altyapı ekranı ile herhangi bir sisteme entegre olmak istenirse yukarıdaki Bean ezilmesi yeterli olacaktır. Varsayılan olarak inmemory çalışmaktadır. Kullanıcı bilgileri 'application-hvl-web-security.yml' içerisinden tanımlanmaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-web-security.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.security', name: 'hvl-security-web-starter'


Cloud Security#

Security paketinin cloud yapısına uygun entegre edilmesi ile oluşan altyapı bileşenidir. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.


JWT Session Provider#

HvlSecuritySessionProvider sınıfının cloud entegrasyonunu sağlamaktadır. HvlCloudJwtSessionProviderImpl implementasyonu ile kimlik doğrulama yapılacak uygulama ile entegre olmaktadır.

NOT: EKSEN varsayılan olarak KEYSIS ürünü ile entegre çalışmaktadır.


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-hvl-security.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cloud.security', name: 'hvl-cloud-jwt-session-provider'


Session Provider#

Güvenlik katmanında kimlik doğrulama işlemi için entegrasyon arayüzü sağlanmaktadır. Güvenlik katmanı ile entegre olacak uygulamanın bu arayüze uygun servis ucu açması gerekmektedir.

NOT: KEYSIS ürününde 'session-server' kimlik yönetimi için entegre durumdadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-hvl-security.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cloud.security', name: 'hvl-cloud-security-session-provider'


Cache#

Uygulamalarda in-memory ve distributed cache yeteneklerini sağlayan altyapı bileşenidir. Caffeine cache ve redis cache destekleri sağlanmaktadır. Bu altyapı bileşeni ihtiyaçlar doğrultusunda genişletilebilmektedir.

ÖNERİ: Cache kullanımının DTO üzerinden yapılması tavsiye edilmektedir. Gereksiz ve çok değişecek veriler cache'e konulmamalıdır.


Core#

Uygulamada cache yönetimi için HvlCacheManager sınıfı sunulmaktadır. Böylece uygulama içerisinde annotion dışında cache yönetimi yapılmaktadır.

NOT: hvl-cache-core kütüphanesi kullanılan sağlayıcıya göre entegrasyon göstermektedir. (Redis, EhCache, Caffeine vb...)


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cache', name: 'hvl-cache-core'


Redis#

Java dünyasında Redis ile entegrasyon için kullanılan en popüler teknolojiler Jedis ve Lettuce'dur. EKSEN tarafından bu iki teknolojiye de destek verilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cache', name: 'hvl-redis'

drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-redis.yml' dosyasıyla konfigure edilebilmektedir.



Caffeine#

EKSEN, in memory olarak çalışan caffeine cache desteği sağlamaktadır. In memory cache kullanımları için oldukça performanslı çalışır.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.cache', name: 'hvl-caffeine'

drawing Nasıl konfigüre edilir?
spring:
  cache:
    type: caffeine


Data#

Uygulamalarda veri katmanında kullanılacak fonksiyonların sağlandığı altyapı bileşenidir. ORM işlemleri için JPA ve QueryDSL teknolojileri tercih edilip bu teknolojiler üzerinde özelleştirmeler yapılmıştır. Auditing altyapısı için Javers ve Envers teknolojilerine destek verilmektedir. Aynı zamanda sorgulama, view, auditing için özelleştirilmiş yetenekler sağlamaktadır ve ldap, redis gibi teknolojilerin veri katmanı destekleri de bu bileşende bulunmaktadır. Başlıca sağlanan katmanlar:

  • Javers, Envers
  • Model
  • Entity
  • JDBC İlklendirme
  • PreLiquibase
  • Model Çeviricileri
  • Hibernate Anotasyonları


Converter#

Converter bileşeni Hibernate, JPA teknolojilerine bağlı olmadan nesneler arası dönüştürücüleri sağlamaktadır. Aynı zamanda enum sınıfların ordinal dışında veritabanı işlemleri için dönüştürücüsünü sağlamaktadır.

NOT: HvlGenericConverter ve HvlGenericHibernateConverter sınıfları runtime anında reflection ile çalıştığı için performansal olarak önerilmemektedir. HvlGenericHibernateConverter dönüştürücüsü hibernate annotation'larına göre davranış göstermektedir. Herhangi bir veritabanı bağlılığı gerekmemektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-converter'


JPA#

Veritabanı işlemlerini sağlayan altyapı bileşenidir. Veritabanı işlemlerini yapacak olan sınıflar declarative olarak sağlanmaktadır.

Hibernate enhancement plugin desteği ile varsayılan olarak 'dynamic update' aktif sunulmaktadır. Eğer sınıfta 'dynamic update' çalışması istenmiyorsa @HvlDynamicUpdateExclude annotation kullanılmalıdır.

NOT: 'dynamic update' performans için önemlidir. Varitabanı işlemlerinde 'update' işleminde sadece değişen alanların gönderilmesini sağlamaktadır.

JPA kullanırken transaction kullanımı önemlidir. Transaction için @Transactional annotation'ını kullanılmaktadır. @Transactional annotation'ını unchecked exception'larda direkt rollback almaktadır. Fakat checked işlemleri için geliştiricinin bu durumu ele alması beklenmektedir. Altyapıda bütün checked hatalar için rollback aktif olması için @HvlTransactionalRollbackForCheckedException annotation'ı bulunmaktadır.

Altyapıda veritabanı işlemlerinde kolon bazlı şifreleme yeteneği bulunmaktadır. @Convert annotation'ı ile kullanılmaktadır.

import javax.persistence.Convert;

@Convert(converter = HvlStringCryptoConverter.class)
private String identityNumber;

NOT: Kolon şifreleme aktif etmek için 'application-database-datasource.yml' içerisinde spring.jpa.properties.hibernate.encryption_enabled alanının true yapılması gerekmektedir. Altyapı olarak şifreleme algoritması olarak şu anda AES desteklenmektedir. AES üzerinden şifreleme işleminde kullanılacak olan key değeri spring.jpa.properties.hibernate.encryption_key alanından verilmesi gerekmektedir.

Altyapı kullanılarak yapılan veritabanı işlemlerinde işlemi kimin yaptığı, tarihi gibi işlem sırasında otomatik verilmesi gereken değerler HvlJpaAwareProvider sınıfı ile yönetilmektedir. Geliştiriciler tarafından özelleştirilebilir.

JPA ile ilgili içeriğe ulaşmak için HvlJpaContext veya HvlJpaContextHolder sınıfı kullanılmalıdır.

Veritabanı işlemleri için altyapıdan PostgreSQL ve Oracle veritabanları için dialect bulunmaktadır. Bu dialect'ler özelleştirilmiştir. Örneğin; PostgreSQL için ilike vb. fonksiyonlar eklenmiştir.

NOT: Dialect, 'application-database-datasource.yml' içerisinde spring.jpa.properties.hibernate.dialect alanınından yönetilmektedir. Kullanılmak istenen dialect paket bilgisi ile verilmelidir. Postgresql için tr.com.havelsan.javarch.data.jpa.dialect.postgresql.HvlPostgreSQL10Dialect ve Oracle için tr.com.havelsan.javarch.data.jpa.dialect.oracle.HvlOracleSQL12cDialect altyapıdan sağlanan dialect'lerdir.

Altyapının sağladığı declarative repository sınıflarını kullanabilmek için konfigurasyon sınıfına aşağıdaki annotation eklenmelidir.

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import tr.com.havelsan.javarch.data.jpa.factory.HvlJpaRepositoryFactoryBean;

@EnableJpaRepositories(basePackages = {"base_package"},
        repositoryFactoryBeanClass = HvlJpaRepositoryFactoryBean.class)

Veritabanı sorguları için Querydsl teknolojisi kullanılmaktadır. Altyapıya özgü alanların varsayılan değerlerinin verildiği ve sorgu (predicate) oluşturmaya yarayan HvlBaseQueryGenerator sınıfından türeyen HvlEntityQueryGenerator ve HvlViewQueryGenerator sınıfı bulunmaktadır.

NOT: Sorgulama işlemi için bu sınıflardan türeyen sınıfları kullanmak önerilmektedir. 'Soft delete' gibi özel yapılar için yapılan değişiklikler desteklenmektedir. Geliştiricinin ekstra kontrol veya ekleme yapmasına gerek yoktur.

Veritabanı işlemleri için altyapı tarafından 4 tane arayüz sağlanmaktadır:

  • HvlJpaRepository: HvlEntity sınıfından türeyen sınıflar için kullanılan arayüzdür.
  • HvlJpaSearchRepository: Sorgulama ile ilgili fonksiyonların sağlandığı arayüzdür.
  • HvlJpaSimpleRepository: HvlSimpleEntity sınıfından türeyen sınıflar için kullanılan arayüzdür.
  • HvlJpaViewRepository: HvlView annotation'a sahip entity sınıfları için persist yeteneklerinin bulunmadığı arayüzdür.

Validasyon işlemleri için 2 adet anotasyon sağlanmaktadır:

  • @HvlIdValid: Model ve entity içerisindeki obje alanlarda id alanı validasyonu yapmak için kullanılır.
    public class HvlOAuthUserModel extends HvlModel {
    
        ..
    
        @HvlIdValid
        private HvlOAuthUserDetailModel userDetail;
    
        ..
    }
    
  • @HvlUuidValid: Model ve entity içerisindeki obje alanlarda uuid alanı validasyonu yapmak için kullanılır.
    public class HvlOAuthProfileDetailModel extends HvlModel {
    
       ..
    
        @NotNull
        @HvlIdValid
        private HvlOAuthProfileDetailTypeModel profileDetailType;
    
        @HvlUuidValid
        private HvlOAuthProfileDetailModel parent;
    
        ..
    
    }
    

drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-database-datasource.yml, application-hvl-data.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa'


Envers#

Veritabanı işlemlerinin izini tutmak için Envers teknolojisi kullanılmaktadır. Envers, nesnenin üzerinde yapılan işlemleri nesnenin tablo isminin sonuna _AUD eklediği tablo üzerinde tutmaktadır.

Altyapıdan gelen declarative repository kullanımı için aşağıdaki konfigurasyon eklenmelidir.

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import tr.com.havelsan.javarch.data.jpa.envers.factory.HvlEnversJpaRepositoryFactoryBean;

@EnableJpaRepositories(basePackages = {"base_package"},
        repositoryFactoryBeanClass = HvlEnversJpaRepositoryFactoryBean.class)

EKSEN, envers veritabanı işlemleri için altyapı tarafından 4 tane arayüz sağlanmaktadır:

  • HvlEnversJpaRepository: HvlEntity sınıfından türeyen sınıflar için kullanılan arayüzdür.
  • HvlEnversJpaLocalizedRepository: HvlLocalizedEntity sınıfından türeyen sınıflar için kullanılan arayüzdür.

drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-database-datasource.yml, application-hvl-data.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-envers'
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-envers-redis-service'
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-envers-service'


Session Aware#

Veritabanı işlemleri sırasında mevcut session'daki kullanıcı bilgisini ve işlem yapılan tarih saat bilgisini sağlayan EKSEN bileşenidir. Bu bilgilerin veritabanı kayıtlarına otomatik olarak eklenmesi isteniyorsa bu bileşen kullanılmalıdır.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-session-aware-configuration'

NOT: Özelleştirilmesi gereken durumlarda bu bileşen devreden çıkarılmalı ve HvlJpaAwareProvider arayüzü implement edilmelidir.


Redis Second Level Cache#


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-database-datasource.yml, redisson-slc.yaml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-slc-redis'


Redis#

Redis'in manuel olarak kullanılması gerektiği durumlar için EKSEN tarafından sağlanan bileşendir. RedisTemplate sınıfı bean olarak EKSEN tarafından konfigüre edilerek sağlanır.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-data-jpa-slc-redis'


Domain Model#

EKSEN tarafından sağlanan Entity sınıflarının sunulduğu bileşendir. Aynı zamanda UUID generator, Sequence generator, veritabanı işlemi esnasında UUID ayarlama özellikleri bu bileşenden sağlanmaktadır. hvl-data-jpa bileşeninin kullanıldığı durumlarda bu bileşen de gelmektedir.

Sağlanan Entity sınıfları şunlardır:

  • HvlEntity: Temel entity sınıfıdır.
  • HvlHardDeleteEntity
  • HvlSoftDeleteEntity
  • HvlLocalizedEntity
  • HvlLookupEntity
  • HvlSimpleEntity: id bilgisi içermeyen entity sınıfıdır.

Sağlanan UUID Generator strategy sınıfları şunlardır:

  • HvlEntityDCESecurityBasedUUIDGeneratorStrategy
  • HvlEntityDCESecurityBasedUUIDGeneratorStrategy
  • HvlEntityRandomBasedUUIDGeneratorStrategy
  • HvlEntityTimeBasedUUIDGeneratorStrategy
  • HvlEntityTimeOrderedBasedUUIDGeneratorStrategy
  • HvlEntityTimeOrderedWithMACBasedUUIDGeneratorStrategy
  • HvlEntityTimeWithMACBasedUUIDGeneratorStrategy

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-domain-model'


DTO Model#

EKSEN tarafından sağlanan Model sınıflarının sunulduğu bileşendir.

Sağlanan modeller şunlardır:

  • HvlModel: Temel model sınıfıdır.
  • HvlLocalizedModel
  • HvlLookupModel
  • HvlSimpleModel: id bilgisi içermeyen modeldir.
  • HvlQueryModel: Sorgulama işlemleri için kullanılan temel modeldir.

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-dto-model'


Hibernate Annotations#

EKSEN tarafından Hibernate için sağlanan özelliklerin kullanılması için oluşturulmuş olan anotasyonların sağlandığı altyapı bileşenidir. Şu anotasyonlar sağlanmaktadır:

  • @HvlEntitySequence: Bu anotasyon kullanılarak özel sequence isimlendirilmesi yapılabilir. Kullanılmadığı durumlarda veritabanı nesnesindeki tablo ismi ile isimlendirme yapılır.
  • @HvlView: Veritabanında view olarak kullanılacak nesnelerin işaretlenmesini ve maplenmesini sağlayan anotasyondur.

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-hibernate-annotations'


JDBC Initializer#

Veritabanı ilklendirmesinin dosya üzerinden yapılmasını sağlayan bileşendir. Bu bileşen sayesinde veritabanı ilklendirmeleri için senaryolar yazılarak farklı durumlar için ilklendirmeler tetiklenebilmektedir. Senaryo dosyaları içerisinde type bilgisi sql ve ya scenario değerlerini alabilir.

Senaryo içerisindeki elementler sırayla çalışmaktadır ve çalışan elementlerin bilgisi console'a log basılmaktadır.

NOT: Hata alan bir script olursa console'a error logu basılmaktadır ancak diğer scriptler çalışmaya devam etmektedir. Bu yüzden hata durumlarında dikkatli olunmalıdır.

prod.scenario

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Scenario>
    <ScenarioElement type="sql" path="[path]/uniqueConstraint.sql"/>
    <ScenarioElement type="sql" path="[path]/functionalIndex.sql"/>
</Scenario>

dev.scenario

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Scenario>
    <ScenarioElement type="scenario" path="[path]/prod.scenario"/>

    <ScenarioElement type="sql" path="[path]/userType.sql"/>
    <ScenarioElement type="sql" path="[path]/userDetail.sql"/>
    <ScenarioElement type="sql" path="[path]/eventType.sql"/>
    <ScenarioElement type="sql" path="[path]/user.sql"/>
</Scenario>


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-hvl-data.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-jdbc-initializer'


Liquibase Initializer#

Liquibase, veritabanı şeması üzerindeki değişiklikleri yönetmeyi ve versiyonlamayı sağlayan açık kaynaklı bir Java kütüphanesidir. Veritabanı şeması üzerindeki değişikliklerin izlenmesini, yönetilmesini ve uygulanmasını sağlar. Kaba tabirle veritabanı üzerinde versiyon kontrol sistemi kurmamıza yardımcı olur.

Preliquibase ise liquibase scriptlerinden önce çalışarak gerekli veritabanı şemasını oluşturmak gibi işlemleri yapmaktadır.

EKSEN, preliquibase ile varsayılan veritabanı şemalarını otomatik olarak oluşturmaktadır.


drawing Nasıl konfigüre edilir?

hvl-infra altında bulunan 'application-database-liquibase.yml' dosyasıyla konfigure edilebilmektedir.

Konfigürasyonları spring.liquibase ve preliquibase altında bulunmaktadır.

spring:
  liquibase:
    default-schema: ${spring.jpa.properties.hibernate.default_schema}
    change-log: ${LIQUIBASE_CHANGE_LOG:db/changelog-root.yaml}
    enabled: ${LIQUIBASE_ENABLED:false}
    drop-first: ${LIQUIBASE_DROP_FIRST:false}
    url: ${LIQUIBASE_DB_URL:${spring.datasource.url}}
    user: ${LIQUIBASE_DB_USER:${spring.datasource.username}}
    password: ${LIQUIBASE_DB_PASSWORD:${spring.datasource.password}}
    clear-checksums: ${LIQUIBASE_CLEAR_CHECKSUMS:false}
    contexts: ${LIQUIBASE_CONTEXTS:dev}
preliquibase:
  default-schema: ${spring.liquibase.default-schema}
  # sqlScriptReferences: classpath:/db/preliquibase/schema.sql
  dbPlatformCode: postgresql
  • default-schema: Liquibase scriptleri çalıştırırken şema verilmemiş scriptlerde kullanıacak varsayılan veritabanı şema bilgisidir.
  • change-log: Liquibase scriptleri çalıştırırken ilk olarak bakacağı change-log dosyasıdır. Bu dosyanın içerisindeki bilgilere göre sırası ile scriptler çalıştırılmaktadır.
  • enabled: Uygulama ayağa kalkarken liquibase'in devreye girip girmeyeceğini yöneten konfigürasyon bilgisidir.
  • drop-first: Uygulama ayağa kalkarken liquibase'in tüm tabloları temizleyip herşeyi en baştan çalıştırmasını sağlayan konfigürasyon bilgisidir.
  • url: Liquibase'in scriptlerini çalıştıracağı veritabanı url bilgisidir.
  • user: Liquibase'in scriptlerini çalıştıracağı veritabanının kullanıcı adı bilgisidir.
  • password: Liquibase'in scriptlerini çalıştıracağı veritabanının şifre bilgisidir.
  • clear-checksums: Liquibase'in scriptlerinde değişiklik olduğu durumda güncel scriptlerin baz alınacağını belirleyen konfigürasyon bilgisidir. Normal koşullarda liquibase çalıştırdığı bir script değişmişse hata vererek uygulamayı kapatır. Bu konfigürasyon true olduğu durumlarda mevcut checksum ı günceller ve hata atmadan devam eder.

    NOT: Canlı ortamlarda kurulum yapılmışsa çalışmış scriptleri güncellemek son derece tehlikelidir.

  • contexts: Liquibase'in scriptlerini çalıştırırken kullanacağı context bilgisidir. Context ile belirtilmiş changeset leri bu konfigürasyon kapsamında çalıştıracaktır. Virgül kullanılarak birden fazla değer verilebilir.

Preliquibase:

  • default-schema: Şemanın olmadığı durumlarda preliquibase tarafından oluşturulacak şema bilgisidir.
  • sqlScriptReferences: Şema oluşturulması için çalışacak script dosyasının path bilgisidir.
  • dbPlatformCode: Veri tabanı platform bilgisidir. Varsayılan olarak postgresql olarak ayarlanmıştır.

drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-liquibase-initializer'

Proje içerisinden örnek liquibase kullanım yapısı aşağıdaki gibidir.


Model Converter#

Model ve domain nesnesi (entity) arasındaki dönüşümü sağlayan EKSEN bileşenidir. Ek olarak mapstruct için HvlGenericMapStructMapper sınıfını sağlar.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.data', name: 'hvl-model-converter'


Message Broker#

Uygulamalarda message queue yapısının kullanmasını sağlayan altyapı bileşenidir. Kafka desteği sağlanmaktadır.


Kafka#

Kafka ile ilgili detaylı bilgiye ve hvl-kafka kullanımına Kafka sayfasından ulaşılabilir.


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-kafka.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.mq', name: 'hvl-kafka'


Support#

Uygulama mimarisinde ihtiyaç duyulan destek paketlerini içeren altyapı bileşenidir.

  • Elasticsearch Apm Support
  • Spring Batch
  • File System
  • Mail Sender
  • Micrometer Prometheus
  • Multitenancy
  • Sleuth


Apm Support#

EKSEN, bu bileşen ile APM agentlarını instance içerisine ekleyerek Elasticsearch - APM entegrasyonu desteği sağlamaktadır.


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-apm.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-apm-support'


Batch Support#


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-batch.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-batch-support'


File System Support#

Belirli bir path üzerinde dosya işlemleri yapmak için sağlanan bileşendir. HvlFileSystemResourceService sınıfı kullanılarak işlemler yapılmaktadır.

public interface HvlFileSystemResourceService {

    void persistDocument(InputStream document, HvlFileSystemInfoModel resourcePersisterInfo) throws HvlFileSystemException;

    void deleteDocument(HvlFileSystemInfoModel resourcePersisterInfo) throws HvlFileSystemException;

    InputStream readDocument(HvlFileSystemInfoModel resourcePersisterInfo) throws HvlFileSystemException;

    String getDocumentName(HvlFileSystemResourcePathStrategy hvlFileSystemResourcePathStrategy);

}

drawing Nasıl konfigure edilir?
hvl:
  file-system:
    resourcePath: /[path]

Yapılacak dosya işlemleri resourcePath'e verilen path üzerinde gerçekleştirilir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-fs-support'


Mail Support#

EKSEN, mail atmak için gerekli altyapıyı sağlamaktadır. Başlıca yetenekler:

  • Fake mail: Geliştirme ortamları için tüm maillerin sahte bir adrese yönlendirilmesi yapılabilir. Böylece tek bir mail adresi hesabından tüm mailler kontrol edilebilir.
  • Html mail desteği
  • Takvim/Toplantı davetli mail desteği
  • Ekli mail gönderme desteği

Ek olarak mail template'leri ile daha kompleks mailler atılmak isteniyorsa EKSEN tarafından sağlanan ve EKSEN altyapısını kullanan Notification ürünü incelenebilir.


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-hvl-mail.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-mail-support'


Micrometer Prometheus Support#

EKSEN, micrometer kütüphanelerini kullanarak prometheus'a veri basılmasını sağlamaktadır. Böylece Grafana gibi monitoring uygulamaları kullanılarak uygulamalar hakkında detaylı bilgi edinilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-micrometer-prometheus-support'


Multi Tenancy Support#

EKSEN, aynı uygulama üzerinden farklı müşterilere destek verilmesi durumları için multi tenancy support bileşenini sağlamaktadır. Bu bileşen ile aşağıdaki türlerde tenancy sağlanabilmektedir.

  • Veritabanı
  • Veritabanı Şeması
  • Veritabanı Tablo Kolonu
  • Gateway

Veritabanı düzeylerinden birinde multi tenancy yapılmak istendiğinde aşağıdaki entity sınıfları kullanılmalıdır:

  • HvlHardDeleteTenantEntity
  • HvlLookupTenantEntity
  • HvlSimpleTenantEntity
  • HvlSoftDeleteTenantEntity

drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-hvl-multi-tenancy.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-multi-tenancy-support'


Sleuth Support#

EKSEN, cloud ortamlar için tracing yapabilmek amacıyla Sleuth desteği sağlamaktadır. Sleuth instancelar arasındaki networkü izleyerek requestlerin hangi uygulamalardan geçtiğini izlemeyi sağlar. Monitoring tool olarak Zipkin kullanılarak uygulamalar arası network izlenebilir.

Sağlanan @HvlTraceLog anotasyonu ile çalışan methodların da trace edilmesi sağlanmaktadır. Takip edilmek istenen methodların tepesine eklenmesi gerekmektedir.

Logger seviyesi trace yapılarak request ve response'lar detaylı olarak görülebilmektedir.


drawing Nasıl konfigure edilir?

hvl-infra altında bulunan 'application-cloud-sleuth.yml' dosyasıyla konfigure edilebilmektedir.


drawing Uygulamaya nasıl eklenir?
    group: 'tr.com.havelsan.framework.support', name: 'hvl-sleuth-support'