System and method for a compile-time dependency injection and lazy service activation framework
Patent Information
- Authority / Receiving Office
- JP · JP
- Patent Type
- Applications
- Current Assignee / Owner
- ORACLE INT CORP
- Filing Date
- 2023-09-22
- Publication Date
- 2026-04-22
AI Technical Summary
Existing microservices development frameworks require runtime dependency resolution, which can lead to performance issues and lack extensibility, especially in cloud-native applications.
A compile-time dependency injection and lazy service activation framework that uses a service registry to provide meta-information about services and their dependencies, allowing developers to intercept and adapt service usage during code generation, thus avoiding runtime reflection and enabling extensible, static dependency injection.
This approach reduces runtime overhead, improves application performance, and allows for customizable service implementations, ensuring efficient and flexible development of microservices applications.
Smart Images

Figure 00000000_0000_ABST
Abstract
Description
[Technical Field]
[0001] Copyright Notice A portion of the disclosure of this patent document contains material that is subject to copyright protection. The copyright owner has no objection to the facsimile reproduction by anyone of the patent document or the patent disclosure, as it appears in the Patent and Trademark Office patent file or records, but otherwise reserves all copyright rights whatsoever.
[0002] Priority claims This application claims the benefit of priority to U.S. Provisional Patent Application No. 17 / 958,132, filed September 30, 2022, entitled "SYSTEM AND METHOD FOR COMPILE-TIME DEPENDENCY INJECTION AND LAZY SERVICE ACTIVATION FRAMEWORK," the contents of which are incorporated herein by reference.
[0003] Technical Field The embodiments described herein relate generally to cloud computing and software development, and more particularly to systems and methods for providing a compile-time dependency injection and lazy service activation framework with source code generation that can be used to build microservices applications or cloud-native services. [Background technology]
[0004] background A microservices environment presents a software application as a collection of loosely coupled services that are independently deployable and communicate with each other over a network, for example, a cloud network that may be provided by a cloud computing environment.
[0005] A microservices approach may be used, for example, to develop software applications or services that are offered within a cloud computing environment as cloud-native applications or services. Summary of the Invention [Means for solving the problem]
[0006] overview According to one embodiment, a system and method are described herein for providing a compile-time dependency injection and lazy service activation framework with source code generation that can be used to build microservices applications or cloud-native services.
[0007] The framework includes the use of a service registry that provides lazy service activation and meta-information related to one or more services in terms of interfaces or APIs that describe each service's capabilities and each service's dependencies on other services.
[0008] An application's use of a particular service can be intercepted and adapted during compile-time code generation, avoiding the need to use reflection. Extensibility features allow application developers to provide their own templates for code generation or to provide alternative service implementations for use with the application other than the reference implementations provided by the framework.
[0009] Thus, the described systems and methods provide a minimalist, fully static, compile-time based dependency injection framework that can be used with, for example, Java applications and that conforms to injection specifications such as JSR-330. [Brief explanation of the drawings]
[0010] [Figure 1]1A-1D illustrate various examples of a microservices environment that provides a software development framework, according to one embodiment. [Figure 2] FIG. 10 further illustrates various examples of a microservices environment that provides a software development framework, according to one embodiment. [Figure 3] FIG. 10 further illustrates various examples of a microservices environment that provides a software development framework, according to one embodiment. [Figure 4] FIG. 10 further illustrates various examples of a microservices environment that provides a software development framework, according to one embodiment. [Figure 5] FIG. 1 illustrates the use of a microservices environment to develop applications for use as services in a cloud computing environment, according to one embodiment. [Figure 6] FIG. 10 further illustrates the use of a microservices environment to develop applications for use within a cloud computing environment, according to one embodiment. [Figure 7] FIG. 1 illustrates a system that provides a compile-time dependency injection and lazy service activation framework that can be used to develop applications for use in a cloud computing environment, according to one embodiment. [Figure 8] FIG. 1 illustrates the use of compile-time dependency injection when developing an application, according to one embodiment. [Figure 9] FIG. 10 further illustrates the use of compile-time dependency injection when developing an application, according to one embodiment. [Figure 10] FIG. 10 further illustrates the use of compile-time dependency injection when developing an application, according to one embodiment. [Figure 11] FIG. 10 further illustrates the use of compile-time dependency injection when developing an application, according to one embodiment. [Figure 12]FIG. 1 illustrates a method for using a compile-time dependency injection and lazy service activation framework to develop applications for use in a cloud computing environment, according to one embodiment. DETAILED DESCRIPTION OF THE INVENTION
[0011] Detailed Description A microservices environment presents a software application as a collection of loosely coupled services that are independently deployable and communicate with each other over a network, for example, a cloud network that may be provided by a cloud computing environment.
[0012] A microservices approach can be used, for example, to develop software applications or services that are offered within a cloud computing environment as cloud-native applications or services. Software development frameworks such as Helidon support the development of microservices. For example, as described below, Helidon offers various Standard Edition (SE), MicroProfile (MP), and / or Nima programming models or environments, each of which includes a collection of software libraries that support features such as configuration, security, or web server functionality and provides software application developers with a foundation on which to create microservices.
[0013] Generally described, such a software development framework alleviates the need for application developers to program according to a particular tooling or deployment model and enables the execution of microservices without the need for an application server. Helidon libraries can interoperate with other software development, deployment, and / or monitoring tools, such as Docker, Kubernetes, Prometheus, or OpenTracing.
[0014] Microservices Environment 1-4 illustrate various examples of a microservices environment that provides a software development framework, according to one embodiment.
[0015] According to one embodiment, the components and processes illustrated in FIGS. 1-4 may be provided as computer software or program code executable by a computer system or other type of processing device, e.g., a cloud computing system, as further described herein with respect to various embodiments.
[0016] As shown in FIG. 1, according to one embodiment, the Helidon microservices environment 100 can provide the Standard Edition (SE) 110, Macro Profile (MP) 120, and / or Helidon Nima 130 programming models or environments.
[0017] According to various embodiments, the microservices environment may also enable developed applications to interact with cloud, database, or other systems or services 140.
[0018] As shown in FIG. 2, according to one embodiment, the Helidon SE environment supports a functional programming style that directly uses web server, security, and configuration components, providing transparency and control to application developers and supporting Java features such as reactive streams and asynchronous and functional programming.
[0019] According to one embodiment, the Helidon SE environment provides a framework with which application developers can build lightweight reactive microservices. For example, the Helidon SE environment can include various libraries, application program interfaces (APIs), or other components, such as a reactive web server 111 that provides an asynchronous and reactive API for creating web applications, a configuration API 112 that provides a Java API for loading and processing configuration properties in key / value form into config objects that applications can then use to retrieve configuration data, and a security component 113 that provides authentication, authorization, and outbound security, and can also include metrics 114, health checks 115, and tracing 116 or other components.
[0020] As shown in Figure 3, according to one embodiment, the Helidon MP environment supports a declarative programming style through the use of the MicroProfile family of APIs built on top of the Helidon library. MicroProfile definitions (e.g., as specified by the Eclipse MicroProfile project) can be used to support application portability across multiple MicroProfile runtimes.
[0021] For example, according to one embodiment, the Helidon MP environment can include various libraries, APIs, or other components, such as JAX-RS 122, JSON-Proc. 126, CDI 124, metrics 121, health checks 123, fault tolerance 125, MicroProfile configuration 137, and JWT authentication 128 components. The web server can be provided by a non-blocking client / server / web framework 118, such as Netty.
[0022] As shown in FIG. 4, according to one embodiment, the Helidon Nima environment provides a Loom-based implementation of a web server and associated libraries and features that can be used to build cloud-native services.
[0023] For example, according to one embodiment, the Helidon Nima environment may include the use of various components or features that support, for example, HTTP headers 131, client and server connection abstractions 132, router abstractions 133, and connection protocol identification 134, by which application developers can build, for example, blocking (non-reactive) microservices.
[0024] FIG. 5 illustrates the use of a microservices environment to develop applications for use as services in a cloud computing environment, according to one embodiment.
[0025] According to one embodiment, a microservices environment presents software applications as a collection of loosely coupled services that are independently deployable and communicate with each other over a network, for example, a cloud network that may be provided by a cloud computing environment.
[0026] For example, according to one embodiment, the Helidon microservices environment can support the use of a remote procedure call (e.g., gRPC) framework or component that enables applications (client and / or server) to communicate within the microservices environment to build connected systems. The remote procedure call framework allows for the definition of services and methods that can be invoked remotely. The server or service can handle calls from clients through a local object (stub) that allows the client application to directly invoke methods on the server application as if it were a local object. The server / service implements methods to handle client calls, including decoding the incoming request, executing the service method, and encoding the service response. The local object (stub) implements the same methods as the service and wraps the parameters for the call in the appropriate protocol buffer message type, which is then provided as a request to the server.
[0027] FIG. 6 further illustrates the use of a microservices environment to develop applications for use within a cloud computing environment, according to one embodiment.
[0028] As shown in FIG. 6, according to one embodiment, the microservices library allows access by client applications to communicate with the microservices or interact with cloud, database, or other systems or services to access data, process transactions, or perform other operations related to these systems or services.
[0029] The above-described examples of various embodiments of a Helidon microservices environment are provided to illustrate exemplary microservices computing environments. According to various embodiments, the systems and methods described herein may be used with other types of microservices or computing environments.
[0030] Compile-Time Dependency Injection According to one embodiment, described herein are systems and methods for providing a compile-time dependency injection and lazy service activation framework (referred to in some embodiments herein as Pico) that enables application developers using the system to build microservices applications or cloud-native services, including generating source code that reflects dependencies.
[0031] According to one embodiment, the framework includes the use of a service registry that provides lazy service activation and meta-information related to one or more services in terms of interfaces or APIs that describe the functionality of each service and the dependencies of each service on other services.
[0032] According to one embodiment, an application's use of a particular service can be intercepted and adapted during compile-time code generation, avoiding the need to use reflection. Extensibility features allow application developers to provide their own templates for code generation or to provide alternative service implementations for use with the application other than the reference implementations provided by the framework.
[0033] Thus, the described systems and methods provide a minimalist, fully static, compile-time-based dependency injection framework that may be used with, for example, Java applications and that conforms to injection specifications such as Java Specification Request 330 "Dependency Injection Standard for Java" (JSR-330).
[0034] FIG. 7 illustrates a system that provides a compile-time dependency injection and lazy service activation framework that can be used to develop applications for use in a cloud computing environment, according to one embodiment.
[0035] As shown in FIG. 7 , a user (e.g., an application developer) can interact with the compile-time dependency injection and lazy service activation framework 200, including its compile-time dependency injection 210 and service activation 220 features, to develop and compile an application that includes dependency injection 230 and prepare the application as compiled code 240 for activation and execution within a cloud computing environment, e.g., as a microservices application or a cloud-native service.
[0036] According to various embodiments, a compile-time dependency injection and lazy service activation framework provides components, processes, and features including, for example: Dependency injection - involves the assignment of a service instance to a correspondingly annotated field or method setter within the application being developed, i.e., an injection point (e.g., @inject or another form of dependency injection annotation).
[0037] Injection Plan - A process implemented by the framework that determines how an application is developed will resolve each injection point associated with an injection plan. The injection plan may optionally be implemented by the system at compile time. Alternatively, when the injection plan is followed at runtime, the injection plan may be resolved by the framework without the need for reflection, allowing the framework to adhere to native image restrictions and provide application performance benefits.
[0038] Service - one or more class types in the application being developed that represent data processing or logic, e.g. business logic, e.g. beans with the @service annotation.
[0039] Scope - The cardinality of the service instances for the application being developed.
[0040] Singleton - Singleton scope for the service as needed, for example jakarta.inject.Singleton or javax.inject.Singleton. This is the default scope for services provided within the framework.
[0041] Provided - The provided scope of the service, for example jakarta.inject.Provider or javax.inject.Provider, as appropriate. If the service's scope is not Singleton (described above), then the scope is considered to be Provided scope, and its cardinality will be attributed to the Provider implementation determining the cardinality. The provider can optionally use the injection point context to determine the appropriate instances and / or cardinality for the provider to provide.
[0042] Contract - The process by which a service can alias itself for injection. A contract may be provided as an interface or API, e.g., an abstract base class definition, of a service implementation. Injection points can be included using contracts or services known to the framework through compile-time annotation processing.
[0043] Qualifier - Optionally, meta-information or annotations that may originate from other annotations, for example, jakarta.inject.qualifier or javax.inject.qualifier. According to one embodiment, the built-in qualifier type is @Named in the same package.
[0044] Dependencies - Another way of describing injection points that represent, for example, data processing or logic that is considered a dependency, perhaps indicated as bounded or optional with respect to another service or contract.
[0045] Activator (Service Provider) - Code generated by the framework to handle lazily activating service instances in the service registry, e.g., resolving dependencies within the service instance along with injecting any fields or methods that are required to be satisfied as part of the activation process.
[0046] Service Registry - A collection of all services known to the framework and application runtime.
[0047] Module - A process or component by which a developed application binds services to a service registry, which may be code-generated by the system and may include, for example, one module per Java Archive (JAR) or module in an application.
[0048] 8-11 further illustrate the use of compile-time dependency injection when developing an application, according to one embodiment.
[0049] In some software development environments that utilize dependency injection, application classes are analyzed at runtime to detect injection points, for example, as described in an attached XML or JSON file.
[0050] According to one embodiment described herein, a compile-time dependency injection and lazy service activation framework performs its dependency injection process instead of at compile time using one or more compile-time and / or runtime libraries that can accommodate common use cases.
[0051] According to one embodiment, the framework supports the use of an inversion-of-control programming model. For example, with a traditional control-flow programming model, an application developer prepares application code that defines program calls to, for example, libraries to perform a particular task, but the inversion-of-control programming model inverts the flow of control so that the framework instead calls the application code prepared by the developer to perform the particular task.
[0052] According to one embodiment, because the framework can work with the abstraction of modules or classes rather than being required to work with specific implementations backing the classes, it can be used with Helidon or other microservices environments, examples of which are shown above, that allow application developers to use traditional control flow programming models or inversion of control programming models depending on their preferences and development needs.
[0053] According to one embodiment, the framework can be similarly used beyond or independent of a Helidon-type microservices environment, for example, for any Java programming or development environment where an inversion of control programming model is desired.
[0054] As shown in FIG. 8, according to one embodiment, each of one or more software objects A234, B235 in the application being developed is associated with an injection point, which will be resolved at compile time by the framework according to the injection plan 232 for one or more services A262, B264 and to provide service instances 236, 237, respectively.
[0055] According to one embodiment, software classes are generated by the framework at compile time, allowing application developers to inspect their application programs and detect possible problems, for example, before runtime. Application developers also have the opportunity to more closely examine the code that is generated. Providers can further extend the framework for use with other source code generation and dependency injection processes.
[0056] For example, JSR-330 provides various types for use in dependency injection, allowing backing implementations to be written at compile time: classes can be generated according to a dependency graph and plugged into an application at compile-time injection points.
[0057] According to one embodiment, the framework can utilize multiple types of directives or annotations to generate dependencies in application source code, e.g., JARs, at compile time, such that the dependencies are provided as, e.g., Java, source code within the application program itself, and are validated. The process results in applications with a smaller footprint and improved, e.g., faster, runtime performance.
[0058] 9, according to one embodiment, the framework annotation processor looks for, for example, the standard jakarta / javax inject and jakarta / javax annotation types. When these types are found in a class being compiled, for example, by javac, the framework will trigger the creation of an activator (service provider) 268, 269 for that service class / type.
[0059] For example, if an application being developed includes a FooImpl class that implements the Foo interface, and the FooImpl class includes an @Inject or @Singleton annotation, the presence of either of these annotations will trigger the framework to create an appropriate activator (e.g., FooImpl$$picoActivator).
[0060] According to one embodiment, activators are used (a) to describe the service in terms of what service contract (i.e., interface) is advertised (e.g., for FooImpl shown above, this would include Foo if Foo is annotated with @Contract or if "io.helidon.pico.autoAddNonContractInterfaces=true" is used at compile time), and (b) to provide the lifecycle for the service, including creation, invoking injection-based setters, and any, e.g., PostConstruct or PreDestroy methods.
[0061] As shown in FIG. 10, according to one embodiment, when one or more activators are created at compile time, modules X 243, Y 247 (e.g., picoModule) are similarly created to aggregate services for a given module. ``` java @Generated({"provider=oracle", "generator=io.helidon.pico.tools.creator.impl.DefaultActivatorCreator", "ver=1.0-SNAPSHOT"}) @Singleton @Named(picoModule.NAME) public class picoModule implements Module { static final String NAME = "pico.examples.logger.common"; @Override public Optional <string>getName() { return Optional.of(NAME); } @Override public String toString() { return NAME + ":" + getClass().getName(); } @Override public void configure(ServiceBinder binder) { binder.bind(io.helidon.pico.examples.logger.common. AnotherCommunicationMode$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. Communication$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. DefaultCommunicator$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. EmailCommunicationMode$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. ImCommunicationMode$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. LoggerProvider$$picoActivator.INSTANCE); binder.bind(io.helidon.pico.examples.logger.common. SmsCommunicationMode$$picoActivator.INSTANCE); } } ``` At initialization, all of the modules will be located using a service locator (eg, ServiceLocator) and each service will be bound (268, 269) to a service registry 266.
[0062] According to one embodiment, if an annotation within a service is meta-annotated with the InterceptedTrigger annotation, an extra service type is created. For example, in the case of FooImpl shown above, if FooImpl is found to have such an annotation, a FooImpl$$pico interceptor will also be created, along with an activator for that interceptor. The interceptor will be created with a higher weight than FooImpl and will therefore be considered "preferred" when a single @inject is used on Foo or FooImpl. If a list is injected, the interceptor will appear towards the top of the list, again avoiding the need for reflection on the generated class. Any invocation to Foo / FooImpl will be interceptable by any interceptor that is @Named to handle that type's name.
[0063] As shown in FIG. 11, according to one embodiment, the application as-compiled code including its modules 244, 248 can then be activated and executed within a cloud computing environment, for example as a microservices application or a cloud-native service.
[0064] According to one embodiment, a Maven plugin can optionally be used to avoid lookup resolution at runtime within each service activation. At startup, the framework will attempt to use the application module first to avoid lookups. Best practice is to apply the maven-plugin to create-application on the maven assembly - this is typically the "final" application module that depends on all other services / modules in all your deployed applications. The maven-plugin can also be used to create dependency injection support types (e.g., activators, modules, interceptors, applications, etc.) from introspecting external JARs.
[0065] According to one embodiment, modules are generated by a framework based on templates that may be provided by the system or by the user. During compilation, services can indicate which contracts and dependencies they provide. The framework then provides a reification of all services (and all modules) in the application. This provides the application developer with a view into the application code, such as which specific implementations are bound to which specific services.
[0066] In the following example, the framework generates a suggested module-info.java that includes an analysis of the application injection plan or dependency model: ``` . / target / classes / module-info.java.pico / / @Generated({"provider=oracle", "generator=io.helidon.pico.tools.creator.impl.DefaultActivatorCreator", "ver=1.0-SNAPSHOT"}) module pico.examples.logger.common { exports io.helidon.pico.examples.logger.common; / / pico module - generated by io.helidon.pico.tools.creator.impl.DefaultActivatorCreator provides io.helidon.pico.spi.Module with io.helidon.pico.examples.logger.common.picoModule; / / pico external contract usage - generated by io.helidon.pico.tools.creator.impl.DefaultActivatorCreator requires pico.examples.logger.common; uses io.helidon.pico.examples.logger.common.CommunicationMode; uses io.helidon.pico.examples.logger.common.Communicator; uses jakarta.inject.Provider; uses javax.inject.Provider; / / pico-generated by io.helidon.pico.tools.creator.impl.DefaultActivatorCreator requires transitive io.helidon.pico; / / pico application - generated by io.helidon.pico.maven.plugin.ApplicationCreatorMojo provides io.helidon.pico.spi.Application with io.helidon.pico.examples.logger.common.picoApplication; } ``` In the above example, the framework can determine or infer what this module exports and which modules are required due to which external contracts for use during compilation of the application.
[0067] Extensible SPI According to one embodiment, the compile-time dependency injection and lazy service activation framework provides an extensible SPI-based mechanism that allows provided services to be overridden, extended, or replaced with implementations different from those provided by included built-in reference implementation modules. To be a provider implementation, a provider must supply an implementation for a Pico service that is discoverable by a ServiceLoader with a higher-than-default Weight.
[0068] According to one embodiment, SPI class definitions from the io.helidon.pico.spi package are considered primordial and therefore should not participate in injection or be considered traditionally injectable. Service classes that are not targets for injection are found by the standard ServiceLocator in / META-INF / services / <serviceclassname>should be expressed under
[0069] Providers are encouraged to fail-fast during compile time, which suggests a set of tooling that can be applied to create and validate the completeness of the dependency graph at compile time instead of at runtime. Providers are also encouraged to avoid reflection entirely at runtime and advertise their capabilities and configuration using, for example, PicoServicesConfig.
[0070] Module According to one embodiment, the compile-time dependency injection and lazy service activation framework provides various modules, including, for example: api module - APIs and SPIs for frameworks (e.g. Pico); depends on jakarta-inject and jakarta-annotation. Required as a maven compile-time dependency for runtime consumption.
[0071] pico module - Contains the default JSR-330 implementation of the (Pico) API / SPI; depends on the api module. Require it as a maven compile-time dependency for runtime consumption.
[0072] tools module - Contains libraries for template-based code generation and model validation tooling. This is only required at build time, not at runtime.
[0073] processor module - contains libraries for annotation processing; depends on tools. It is only required at build time, not at runtime.
[0074] maven-plugin module - provides a code generation wrapper for maven; depends on tools. It is only required at build time, not runtime.
[0075] Types module According to one embodiment, the types module contains types that are generally applicable to any (e.g., Pico-based) application implementation. The API is consumer-oriented and small, as most of the supported types actually come from the javax / jakarta inject and annotation modules. The SPI package supports the runtime implementation and will not be of interest to the majority of application developers who generally use dependency injection. The only aspects of the SPI that need to be used directly are the Pico services and service classes, as these are used to activate one or more of the startup services that comprise the (Pico) application.
[0076] Tools Module According to one embodiment, the default tools module is responsible for providing basic tooling around code generation and dependency model analysis during compile time. All services are standard ServiceLocator based and all use the standard request / response mechanism in the API. io.helidon.pico.tools.creator.ApplicationCreator This tool creates, for example, a picoApplication. io.helidon.pico.tools.creator.ActivatorCreator This tool creates, for example, picoActivator(s) and picoModule(s). io.helidon.pico.tools.creator.ExternalModuleCreator This tool creates a request to parse a third-party JAR and then generates the appropriate request payload for handoff to the ActivatorCreator tool to generate the code. io.helidon.pico.tools.creator.InterceptorCreator This tool is invoked when an InterceptorTrigger is found on a service that requests interception.
[0077] Processor module According to one embodiment, the default-tools-processor module is designed to provide compile-time only annotation processing and support dependency injection models in a standard, e.g., JSR-330 compliant, way at runtime, including looking for javax / jakarta inject type annotations and then code-generate supporting dependency injection classes, and leveraging the tools module to perform the necessary code generation when these annotations are found.
[0078] As an example, while creating their application, application developers can modify the pom.xml to add this plugin which will be executed as part of the compilation phase. ``` <plugin> <groupid> org.apache.maven.plugins< / groupid> <artifactid> maven-compiler-plugin< / artifactid> <configuration> <forcejavaccompileruse> true< / forcejavaccompileruse> <annotationprocessorpaths> <path> <groupid> io.helidon.pico< / groupid> <artifactid> helidon-pico-processor< / artifactid> <version> ${helidon.version}< / version> < / path> <!-- optionally handle javax also (the default is jakarta.*) --> <path> <groupid> javax.inject< / groupid> <artifactid> javax.inject< / artifactid> <version> ${javax.injection.version}< / version> < / path> <path> <groupid> javax.annotation< / groupid> <artifactid> javax.annotation-api< / artifactid> <version> ${javax.annotations.version}< / version> < / path> < / annotationprocessorpaths> < / configuration> < / plugin> ``` More Features According to one embodiment, the compile-time dependency injection and lazy service activation framework provides a means to generate "activators" (dependency injection support types) and supporting javax annotated types for externally constructed modules.
[0079] According to one embodiment, if a service includes an annotation that is itself annotated with an InterceptorTrigger, the code generated for that service will support interception. The compile-time dependency injection and lazy service activation framework provides meta-information about each service in its service registry, including information such as which contracts are offered by each service and which contracts describe its dependencies.
[0080] According to one embodiment, the compile-time dependency injection and lazy service activation framework generates a suggested module-info.java file for your module (look for module-info.java.pico under . / target / classes or . / target / test-classes).
[0081] According to one embodiment, a compile-time dependency injection and lazy service activation framework provides a maven plugin that allows injection graphs to be (a) validated for completeness and (b) deterministically bound to service implementations at compile time. This is demonstrated in each of the examples, and the results lead to early detection of problems at compile time instead of runtime, as well as significant performance improvements.
[0082] According to one embodiment, Testable( * ) The Services module t provides a set of types for facilities to create fake / mock services for various test scenarios. ``` <dependency> <groupid> io.helidon.pico< / groupid> <artifactid> helidon-pico-test-support< / artifactid> <version> ${helidon.version}< / version> <scope> test< / scope> < / dependency> ``` According to one embodiment, the framework is designed to be extensible from the micro level (application developers can override mustache / handlebar templates) to the macro level (application developers can provide their own implementations of SPIs).
[0083] Exemplary Methods FIG. 12 illustrates a method for using a compile-time dependency injection and lazy service activation framework to develop applications for use in a cloud computing environment, according to one embodiment.
[0084] As shown in FIG. 12 , according to one embodiment, in step 282, a computer including one or more processors and memory provides a microservices environment (microservices library) and, in connection with the microservices environment, a compile-time dependency injection and lazy service activation framework that supports the use of inversion of control as a programming model.
[0085] In step 284, one or more services are made available for injection, and the contract provides an interface or abstract base class definition of the service implementation for use with an injection point at compile time.
[0086] In step 286, within the application being developed, injection points act as assignments of service instances to field or method setters annotated with @inject or another form of dependency injection annotation.
[0087] In step 287, the framework creates an activator (service provider) to handle lazily activating the service instance in the service registry and resolving all dependencies along with injected fields, methods, etc. that are required to be satisfied as part of the activation process.
[0088] In step 288, the framework instead evaluates the injection points at application compile time and generates dependencies in the application source code (eg, as the application JAR).
[0089] Exemplary Development Process According to one embodiment, a compile-time dependency injection and lazy service activation framework enables application developers to build microservices applications or cloud-native services.
[0090] As an example, to illustrate the development process, during the creation of their application, an application developer can add annotations to, for example, the pom.xml or gradle.build file. Annotation Processor Dependencies / Paths: ``` <groupid> io.helidon.pico< / groupid> <artifactid> helidon-pico-processor< / artifactid> <version> ${helidon.version}< / version> ``` Compile-time dependencies: ``` <dependency> <groupid> io.helidon.pico< / groupid> <artifactid> helidon-pico< / artifactid> <version> ${helidon.version}< / version> < / dependency> ``` According to one embodiment, an application can be developed using the standard jakarta.inject.* and jakarta.annotation.* types, and then built and run. Because the framework effectively owns the creation of services according to the scope in which each service is declared, application developers must make requests for the initial service(s) instead of invoking new services directly in their application code. This can be accomplished, for example, by looking up the service directly using the service SPI. ``` Services services = PicoServices.getPicoServices(). orElseThrow().getServices(); ServiceProvider <library>librarySp = services.lookupFirst(Library.class); System.out.println("found a library provider: " + librarySp.getDescription()); Library library = librarySp.get(); ``` In one embodiment, if there is a collection of services that require activation at startup, their service implementation types can be annotated with RunLevel(RunLevel.STARTUP) and appropriate code provided in main() to lazily activate those services.
[0091] Whenever list-based injection is used, all services that match the injection criteria will be in the injected (and immutable) list. The list is organized according to the Weight annotation value, which ranks them from most weighted to least weighted. If a service is not explicitly weighted, a default weight will be assigned. If the weights are the same for two services, a secondary ordering will be based on the FN class name of the service type.
[0092] Weight determines the list order, while the RunLevel annotation is used to rank the startup ordering from lowest to highest, where RunLevel.STARTUP == 0. Application developers are expected to activate these directly using code such as the following (get() lazily creates and activates the underlying service type): ``` List <ServiceProvider <object>> startupServices = services .lookup(DefaultServiceInfo.builder() .runLevel(RunLevel.STARTUP).build(), true); startupServices.stream().forEach(ServiceProvider::get); ``` If the ordering of the list of services is important, the application developer can use the Weight and / or RunLevel annotations to establish priority, weighted ordering, or startup ordering.
[0093] According to various embodiments, the teachings herein may be conveniently implemented using one or more conventional general-purpose or special-purpose computers, computing devices, machines, or microprocessors, including one or more processors, memory, and / or computer-readable storage media, programmed according to the teachings of the present disclosure. Appropriate software coding can be readily prepared by skilled programmers based on the teachings of the present disclosure, as will be apparent to those skilled in the software arts.
[0094] In some embodiments, the teachings herein may include a computer program product, which is one or more non-transitory computer-readable storage media having stored thereon / in instructions that can be used to program a computer to perform any of the processes of the present teachings. Examples of such storage media may include, but are not limited to, hard disk drives, hard disks, fixed disks, or other electromechanical data storage devices, floppy disks, optical disks, DVDs, CD-ROMs, microdrives, and magneto-optical disks, ROMs, RAMs, EPROMs, EEPROMs, DRAMs, VRAMs, flash memory devices, magnetic or optical cards, nanosystems, or other types of storage media or devices suitable for non-transitory storage of instructions and / or data.
[0095] The foregoing description has been provided for purposes of illustration and description. It is not intended to be exhaustive or to limit the scope of protection to the precise form disclosed. Many modifications and variations will be apparent to those skilled in the art.
[0096] For example, although various embodiments of the systems and methods described herein are shown for use in a Helidon microservices environment, various embodiments may be used with other types of microservices environments or other computing environments.
[0097] The embodiments were chosen and described to best explain the principles of the present teachings and their practical application, and to thereby enable those skilled in the art to appreciate various embodiments with various modifications suited to the particular uses contemplated. It is intended that the scope be defined by the appended claims and their equivalents.< / object> < / library> < / serviceclassname> < / string>
Claims
1. A system for use with microservices or other computing environments, a computer including one or more processors that provide access to a microservice or other computing environment for use with a software application or service, and a compile-time dependency injection and lazy service activation framework including source code generation that can be used to build microservice applications or cloud-native services, for an application being developed, one or more services are made available for injection, within the application being developed, injection points serve as the assignment of service instances to correspondingly annotated fields or method setters, the system generates an activator that handles resolving dependencies required to be satisfied as part of an activation process, the system is a system that evaluates injection points at compile time and generates dependencies in the application source code.
2. The system of claim 1, including the use of a service registry that provides lazy service activation and meta information related to one or more services with respect to an interface or API that describes the functionality of each service and the dependencies of each service on other services.
3. The system of claim 1 or 2, wherein the use of an application of a particular service is intercepted and adapted during compile-time code generation, avoiding the need to use reflection.
4. The system of claim 1 or 2, wherein the compile-time dependency injection and lazy service activation framework is provided for use with Helidon or other microservice development environments.
5. The system of claim 1 or 2, wherein the system is used to build microservice applications or cloud-native services for execution within a cloud computing environment.
6. A method for use with microservices or other computing environments, A system including compile-time dependency injection and a lazy service activation framework including source code generation, which can be used to build microservice applications or cloud-native services in relation to microservices or other computing environments for use with software applications or services. Regarding the application to be developed, one or more services are made available for injection, within the application to be developed, the injection point serves as the assignment of a service instance to a correspondingly annotated field or method setter, the system generates an activator that handles resolving dependencies that are required to be satisfied as part of the activation process, the system evaluates injection points at compile time and generates dependencies in the application source code, a method.
7. The method according to claim 6, wherein the system includes the use of a service registry that provides lazy service activation and metadata related to one or more services with respect to an interface or API that describes the functionality of each service and the dependencies of each service on other services.
8. The method according to claim 6 or 7, wherein the use of an application of a particular service is intercepted and adapted during compile-time code generation to avoid the need to use reflection.
9. The method according to claim 6 or 7, wherein the compile-time dependency injection and lazy service activation framework is provided for use with Helidon or other microservice development environments.
10. The method according to claim 6 or 7, wherein the system is used to build microservice applications or cloud-native services for execution within a cloud computing environment.
11. A computer-readable program including instructions stored in the computer-readable program, which, when read and executed by a system comprising one or more computers, cause the system to implement a method, the method comprising In connection with microservices or other computing environments for use with a software application or service, including compile-time dependency injection and a lazy service activation framework for source code generation that can be used to build microservice applications or cloud-native services, For the application being developed, One or more services are made available for injection, Within the application being developed, the injection point serves as the assignment of a service instance to a correspondingly annotated field or method setter, The system generates an activator that handles resolving dependencies required to be satisfied as part of the activation process, The system is a computer-readable program that evaluates injection points at compile time and generates dependencies in the application source code.
12. The system includes the use of a service registry that provides lazy service activation and meta-information related to one or more services with respect to an interface or API that describes the functionality of each service and the dependencies of each service on other services, the computer-readable program of claim 11.
13. The use of a particular service in an application can be intercepted and adapted during compile-time code generation, avoiding the need to use reflection, the computer-readable program of claim 11 or 12.
14. The compile-time dependency injection and lazy service activation framework is provided for use with Helidon or other microservices development environments, the computer-readable program of claim 11 or 12.
15. The system is used to build microservice applications or cloud-native services for execution within a cloud computing environment, the computer-readable program of claim 11 or 12.