Pengantar Micronaut Framework

1. Apa Itu Micronaut

Micronaut adalah kerangka kerja berbasis JVM untuk membangun aplikasi modular yang ringan. Dikembangkan oleh OCI, perusahaan yang sama yang membuat Grails, Micronaut adalah kerangka kerja terbaru yang dirancang untuk membuat layanan mikro cepat dan mudah .

Meskipun Micronaut berisi beberapa fitur yang mirip dengan kerangka kerja yang ada seperti Spring, ia juga memiliki beberapa fitur baru yang membedakannya. Dan dengan dukungan untuk Java, Groovy, dan Kotlin, ia menawarkan berbagai cara untuk membuat aplikasi.

2. Fitur Utama

Salah satu fitur paling menarik dari Micronaut adalah mekanisme injeksi ketergantungan waktu kompilasi. Sebagian besar framework menggunakan refleksi dan proxy untuk melakukan injeksi dependensi pada waktu proses. Namun, Micronaut membangun data injeksi ketergantungannya pada waktu kompilasi. Hasilnya adalah startup aplikasi yang lebih cepat dan footprint memori yang lebih kecil.

Fitur lainnya adalah dukungan kelas pertamanya untuk pemrograman reaktif, untuk klien dan server. Pilihan implementasi reaktif tertentu diserahkan kepada pengembang karena RxJava dan Project Reactor didukung.

Micronaut juga memiliki beberapa fitur yang menjadikannya kerangka kerja yang sangat baik untuk mengembangkan aplikasi cloud-native. Ini mendukung beberapa alat penemuan layanan seperti Eureka dan Konsul, dan juga bekerja dengan berbagai sistem pelacakan terdistribusi seperti Zipkin dan Jaeger.

Ini juga memberikan dukungan untuk membuat fungsi lambda AWS, membuatnya mudah untuk membuat aplikasi tanpa server.

3. Memulai

Cara termudah untuk memulai menggunakan SDKMAN:

> sdk install micronaut 1.0.0.RC2

Ini menginstal semua file biner yang kami perlukan untuk membangun, menguji, dan menerapkan aplikasi Micronaut. Ini juga menyediakan alat CLI Micronaut, yang memungkinkan kita memulai proyek baru dengan mudah.

Artefak biner juga tersedia di Sonatype dan GitHub.

Di bagian berikut, kita akan melihat beberapa fitur kerangka kerja.

4. Injeksi Ketergantungan

Seperti yang disebutkan sebelumnya, Micronaut menangani injeksi ketergantungan pada waktu kompilasi, yang berbeda dari kebanyakan container IoC.

Namun, ini masih mendukung penuh anotasi JSR-330 sehingga bekerja dengan kacang mirip dengan kerangka kerja IoC lainnya.

Untuk melakukan autowire kacang ke dalam kode kita, kita menggunakan @Inject:

@Inject private EmployeeService service;

The @Inject penjelasan bekerja seperti @ Autowired dan dapat digunakan pada bidang, metode, konstruktor, dan parameter.

Secara default, semua kacang dicakup sebagai prototipe. Kita bisa dengan cepat membuat kacang tunggal menggunakan @Singleton. Jika beberapa kelas mengimplementasikan antarmuka kacang yang sama, @Primary dapat digunakan untuk mendekonfliknya:

@Primary @Singleton public class BlueCar implements Car {}

The @Requires penjelasan dapat digunakan ketika kacang adalah opsional, atau hanya perform autowiring ketika kondisi tertentu terpenuhi.

Dalam hal ini, ia berperilaku seperti anotasi Spring Boot @Conditional :

@Singleton @Requires(beans = DataSource.class) @Requires(property = "enabled") @Requires(missingBeans = EmployeeService) @Requires(sdk = Sdk.JAVA, value = "1.8") public class JdbcEmployeeService implements EmployeeService {}

5. Membangun Server HTTP

Sekarang mari kita lihat membuat aplikasi server HTTP sederhana. Untuk memulai, kami akan menggunakan SDKMAN untuk membuat proyek:

> mn create-app hello-world-server -build maven

Ini akan membuat proyek Java baru menggunakan Maven dalam direktori bernama hello-world-server. Di dalam direktori ini, kita akan menemukan kode sumber aplikasi utama kita, file POM Maven, dan file pendukung lainnya untuk proyek tersebut.

Aplikasi bawaan yang sangat sederhana:

public class ServerApplication { public static void main(String[] args) { Micronaut.run(ServerApplication.class); } }

5.1. Memblokir HTTP

On its own, this application won't do much. Let's add a controller that has two endpoints. Both will return a greeting, but one will use the GET HTTP verb, and the other will use POST:

@Controller("/greet") public class GreetController { @Inject private GreetingService greetingService; @Get("/{name}") public String greet(String name) { return greetingService.getGreeting() + name; } @Post(value = "/{name}", consumes = MediaType.TEXT_PLAIN) public String setGreeting(@Body String name) { return greetingService.getGreeting() + name; } }

5.2. Reactive IO

By default, Micronaut will implement these endpoints using traditional blocking I/O. However, we can quickly implement non-blocking endpoints by merely changing the return type to any reactive non-blocking type.

For example, with RxJava we can use Observable. Likewise, when using Reactor, we can return Mono or Flux data types:

@Get("/{name}") public Mono greet(String name) { return Mono.just(greetingService.getGreeting() + name); }

For both blocking and non-blocking endpoints, Netty is the underlying server used to handle HTTP requests.

Normally, the requests are handled on the main I/O thread pool that is created at startup, making them block.

However, when a non-blocking data type is returned from a controller endpoint, Micronaut uses the Netty event loop thread, making the whole request non-blocking.

6. Building an HTTP Client

Now let's build a client to consume the endpoints we just created. Micronaut provides two ways of creating HTTP clients:

  • A declarative HTTP Client
  • A programmatic HTTP Client

6.1 Declarative HTTP Client

The first and quickest way to create is using a declarative approach:

@Client("/greet") public interface GreetingClient { @Get("/{name}") String greet(String name); }

Notice how we don't implement any code to call our service. Instead, Micronaut understands how to call the service from the method signature and annotations we have provided.

To test this client, we can create a JUnit test that uses the embedded server API to run an embedded instance of our server:

public class GreetingClientTest { private EmbeddedServer server; private GreetingClient client; @Before public void setup() { server = ApplicationContext.run(EmbeddedServer.class); client = server.getApplicationContext().getBean(GreetingClient.class); } @After public void cleanup() { server.stop(); } @Test public void testGreeting() { assertEquals(client.greet("Mike"), "Hello Mike"); } }

6.2. Programmatic HTTP Client

We also have the option of writing a more traditional client if we need more control over its behavior and implementation:

@Singleton public class ConcreteGreetingClient { private RxHttpClient httpClient; public ConcreteGreetingClient(@Client("/") RxHttpClient httpClient) { this.httpClient = httpClient; } public String greet(String name) { HttpRequest req = HttpRequest.GET("/greet/" + name); return httpClient.retrieve(req).blockingFirst(); } public Single greetAsync(String name) { HttpRequest req = HttpRequest.GET("/async/greet/" + name); return httpClient.retrieve(req).first("An error as occurred"); } }

The default HTTP client uses RxJava, so can easily work with blocking or non-blocking calls.

7. Micronaut CLI

We've already seen the Micronaut CLI tool in action above when we used it to create our sample project.

In our case, we created a standalone application, but it has several other capabilities as well.

7.1. Federation Projects

In Micronaut, a federation is just a group of standalone applications that live under the same directory. By using federations, we can easily manage them together and ensure they get the same defaults and settings.

When we use the CLI tool to generate a federation, it takes all the same arguments as the create-app command. It will create a top-level project structure, and each standalone app will be created in its sub-directory from there.

7.2. Features

When creating a standalone application or federation, we can decide which features our app needs. This helps ensure the minimal set of dependencies is included in the project.

We specify features using the -features argument and supplying a comma-separated list of feature names.

We can find a list of available features by running the following command:

> mn profile-info service Provided Features: -------------------- * annotation-api - Adds Java annotation API * config-consul - Adds support for Distributed Configuration with Consul * discovery-consul - Adds support for Service Discovery with Consul * discovery-eureka - Adds support for Service Discovery with Eureka * groovy - Creates a Groovy application [...] More features available

7.3. Existing Projects

We can also use the CLI tool to modify existing projects. Enabling us to create beans, clients, controllers, and more. When we run the mn command from inside an existing project, we'll have a new set of commands available:

> mn help | Command Name Command Description ----------------------------------------------- create-bean Creates a singleton bean create-client Creates a client interface create-controller Creates a controller and associated test create-job Creates a job with scheduled method

8. Conclusion

In this brief introduction to Micronaut, we've seen how easy it is to build both blocking and non-blocking HTTP servers and clients. Also, we explored some features of its CLI.

But this is just a small taste of the features it offers. There is also full support for serverless functions, service discovery, distributed tracing, monitoring and metrics, a distributed configuration, and much more.

And while many of its features are derived from existing frameworks such as Grails and Spring, it also has plenty of unique features that help it stand out on its own.

Seperti biasa, kami dapat menemukan kode contoh di atas di repo GitHub kami.