Ana içeriğe geç

1.1. 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'

NOT: EKSEN altyapısı kullanılan projelerde bu kütüphaneyi ayrıca sisteme dahil etmeye gerek yoktur. EKSEN altyapısı hvl-util kütüphanesini otomatik olarak sisteme dahil etmektedir.


Ayrıca hvl-util kütüphanesi projeye eklendiğinde aşağıdaki kütüphaneleri de sisteme otomatik olarak ekleyecektir. Bundan dolayı hvl-util, EKSEN altyapısını kullanan projelerin aşağıdaki kütüphaneleri tekrar eklemesine gerek olmayacaktır.

commonsIOVersion=2.15.0
apacheCommonsCollections4Version=4.4
googleGuavaVersion=32.0.1-jre

api(
    [group: 'commons-io', name: 'commons-io', version: commonsIOVersion],
    [group: 'org.apache.commons', name: 'commons-collections4', version: apacheCommonsCollections4Version],
    [group: 'org.apache.commons', name: 'commons-lang3'],
    [group: 'com.google.guava', name: 'guava', version: googleGuavaVersion],
    [group: 'commons-codec', name: 'commons-codec'],
    [group: 'jakarta.servlet', name: 'jakarta.servlet-api'],
    [group: 'org.apache.httpcomponents.client5', name: 'httpclient5'],
)