Skip to main content
ElastiCORE 3.0 is a release candidate: 3.0.261022-rc1 on Maven Central. Projects on the 2.2 line: see the 2.2 documentation.
Version: 3.0

Ports

A port declares, in YAML, a call to another system. The generator writes the interface; at run time a proxy factory implements it. There is no adapter class to write.

In hexagonal terms these are outbound ports: the application knows the interface, the technology is outside.

DirectionWhatNamespace
inboundOrderUseCase - generated by hexagonal-springbootinboundPort
outbound (this section)port: - HTTP, DBMS, gRPCport
outbound, persistenceOrderRepositoryPort - generated by the DDD bundlesdomainRepository
TypeForAt run time
httpREST APIs of other systemsHttpServiceProxyFactory - or a Spring @HttpExchange client with httpPort: spring
dbmsSQL on a databaseDbmsServiceProxyFactory
protogRPCa generated .proto service definition

The shape​

port:
ServiceName:
meta: <type> [options]
methods:
methodName:
meta: method [annotations]
params:
paramName: ParamType
return: ReturnType

Where the interface goes​

env.yml
  namespace:
port: com.example.application.port.out

Not under domain: the contract is written with application DTOs and, when paged, Spring's Page - it is the application's port. A domain service's uses: naming one is ignored with a warning.

Registering the proxies: auto-configuration​

From 3.0.261023 the runtime proxies (HTTP ports in their default mode, DBMS ports) become beans with nothing on the application class. The runtime libraries (elasticore-springboot3 / -springboot4) have a Spring Boot auto-configuration, io.elasticore.springboot.autoconfigure.ElastiCoreAutoConfiguration:

@SpringBootApplication     // nothing else - ports are found in this package and below
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

It looks for ports (@ExternalService, @DbmsService) in the package of the @SpringBootApplication class and below - where Spring Boot finds entities and repositories - so a @SpringBootTest starting that class gets the port beans too. Only if it finds ports does it register:

  • the ports;
  • DbTransactionGateway, which runs the DBMS ports' SQL, when there is one EntityManagerFactory or a @Primary one;
  • ApplicationContextProvider;
  • the banner.

An application without ports gets nothing.

  • @EnableElastiCore still works. With it, each port and bean is registered once; there is no need to remove it.
  • Beans you already have win: a @ComponentScan("io.elasticore.springboot3"), or a @Bean for a port or for DbmsSqlExecutor. A @Primary bean of yours that wraps the proxy keeps the proxy (@Qualifier("CourierPort")).
  • Ports outside the application class's package are not found, including packages added with @SpringBootApplication(scanBasePackages = ...). Use @AutoConfigurationPackage(basePackages = ...) (it also widens entity and repository scanning), @EnableElastiCore on a class in that package, or a @Bean. An unregistered port cannot be injected: No qualifying bean of type 'ShopReportService'.
  • Ports that share a simple name (shop.NotificationPort, billing.NotificationPort) are all registered under their full class names, with a warning. Inject them by type or with @Qualifier("<full class name>").
  • Two or more EntityManagerFactory beans and none @Primary: no executor is created. Mark one @Primary or declare a DbmsSqlExecutor bean.
  • Switching it off: elasticore.autoconfigure.enabled=false; then use @EnableElastiCore. elasticore.banner.enabled=false silences the banner.
  • A plain Spring context without Spring Boot still needs @EnableElastiCore (io.elasticore.springboot3.EnableElastiCore - the Boot 4 runtime has the same package).

The proxies look up their beans (the DBMS executor, HTTP authentication and converters) in their own bean factory, so tests that start several contexts do not see each other's beans.

Up to 3.0.261022-rc1, @EnableElastiCore is required: without it the ports are not beans, and @ComponentScan("io.elasticore.springboot3") does not register them.

Ports with httpPort: spring are Spring's own clients and need neither.

gRPC​

port:
UserGrpcService:
meta: proto @server @client
methods:
getUser:
meta: method -- read a user
params:
input: UserProtoInput
return: UserProtoOutput

@server generates the server side, @client the client; the .proto service definition is generated.

Next: HTTP ports, DBMS ports.