1. Overview
In this tutorial, we’ll showcase microservices development using the MSF4J framework.
This is a lightweight tool which provides an easy way to build a wide variety of services focused on high performance.
2. Maven Dependencies
We’ll need a bit more Maven configuration than usual to build an MSF4J-based microservice. The simplicity and the power of this framework do come at a price: basically, we need to define a parent artifact, as well as the main class:
<parent> <groupId>org.wso2.msf4j</groupId> <artifactId>msf4j-service</artifactId> <version>2.6.0</version> </parent> <properties> <microservice.mainClass> com.baeldung.msf4j.Application </microservice.mainClass> </properties>
The latest version of msf4j-service can be found on Maven Central.
Next, we’ll show three different microservices scenarios. First a minimalistic example, then a RESTful API, and finally a Spring integration sample.
3. Basic Project
3.1. Simple API
We’re going to publish a simple web resource.
This service is provided with a class using some annotations where each method handles a request. Through these annotations, we set the method, the path, and the parameters required for each request.
The returned content type is just plain text:
@Path("/") public class SimpleService { @GET public String index() { return "Default content"; } @GET @Path("/say/{name}") public String say(@PathParam("name") String name) { return "Hello " + name; } }
And remember that all classes and annotations used are just standard JAX-RS elements, which we already covered in this article.
3.2. Application
We can launch the microservice with this main class where we set, deploy and run the service defined earlier:
public class Application { public static void main(String[] args) { new MicroservicesRunner() .deploy(new SimpleService()) .start(); } }
If we want, we can chain deploy calls here to run several services at once:
new MicroservicesRunner() .deploy(new SimpleService()) .deploy(new ComplexService()) .start()
3.3. Running the Microservice
To run the MSF4J microservice, we have a couple of options:
- On an IDE, running as a Java application
- Running the generated jar package
Once started, you can see the result at http://localhost:9090.
3.4. Startup Configurations
We can tweak the configuration in a lot of ways just by adding some clauses to the startup code.
For example, we can add any kind of interceptor for the requests:
new MicroservicesRunner() .addInterceptor(new MetricsInterceptor()) .deploy(new SimpleService()) .start();
Or, we can add a global interceptor, like one for authentication:
new MicroservicesRunner() .addGlobalRequestInterceptor(newUsernamePasswordSecurityInterceptor()) .deploy(new SimpleService()) .start();
Or, if we need session management, we can set a session manager:
new MicroservicesRunner() .deploy(new SimpleService()) .setSessionManager(new PersistentSessionManager()) .start();
For more details about each of this scenarios and to see some working samples, check out MSF4J’s official GitHub repo.
4. Building an API Microservice
We’ve shown the simplest example possible. Now we’ll move to a more realistic project.
This time, we show how to build an API with all the typical CRUD operations to manage a repository of meals.
4.1. The Model
The model is just a simple POJO representing a meal:
public class Meal { private String name; private Float price; // getters and setters }
4.2. The API
We build the API as a web controller. Using standard annotations, we set each function with the following:
- URL path
- HTTP method: GET, POST, etc.
- input (@Consumes) content type
- output (@Produces) content type
So, let’s create a method for each standard CRUD operation:
@Path("/menu") public class MenuService { private List<Meal> meals = new ArrayList<Meal>(); @GET @Path("/") @Produces({ "application/json" }) public Response index() { return Response.ok() .entity(meals) .build(); } @GET @Path("/{id}") @Produces({ "application/json" }) public Response meal(@PathParam("id") int id) { return Response.ok() .entity(meals.get(id)) .build(); } @POST @Path("/") @Consumes("application/json") @Produces({ "application/json" }) public Response create(Meal meal) { meals.add(meal); return Response.ok() .entity(meal) .build(); } // ... other CRUD operations }
4.3. Data Conversion Features
MSF4J offers support for different data conversion libraries such as GSON (which comes by default) and Jackson (through the msf4j-feature dependency). For example, we can use GSON explicitly:
@GET @Path("/{id}") @Produces({ "application/json" }) public String meal(@PathParam("id") int id) { Gson gson = new Gson(); return gson.toJson(meals.get(id)); }
In passing, note that we’ve used curly braces in both @Consumes and @Produces annotation so we can set more than one mime type.
4.4. Running the API Microservice
We run the microservice just as we did in the previous example, through an Application class that publishes the MenuService.
Once started, you can see the result at http://localhost:9090/menu.
5. MSF4J and Spring
We can also apply Spring in our MSF4J based microservices, from which we’ll get its dependency injection features.
5.1. Maven Dependencies
We’ll have to add the appropriate dependencies to the previous Maven configuration to add Spring and Mustache support:
<dependencies> <dependency> <groupId>org.wso2.msf4j</groupId> <artifactId>msf4j-spring</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>org.wso2.msf4j</groupId> <artifactId>msf4j-mustache-template</artifactId> <version>2.6.1</version> </dependency> </dependencies>
The latest version of msf4j-spring and msf4j-mustache-template can be found on Maven Central.
5.2. Meal API
This API is just a simple service, using a mock meal repository. Notice how we use Spring annotations for auto-wiring and to set this class as a Spring service component.
@Service public class MealService { @Autowired private MealRepository mealRepository; public Meal find(int id) { return mealRepository.find(id); } public List<Meal> findAll() { return mealRepository.findAll(); } public void create(Meal meal) { mealRepository.create(meal); } }
5.3. Controller
We declare the controller as a component and Spring provides the service through auto-wiring. The first method shows how to serve a Mustache template and the second a JSON resource:
@Component @Path("/meal") public class MealResource { @Autowired private MealService mealService; @GET @Path("/") public Response all() { Map map = Collections.singletonMap("meals", mealService.findAll()); String html = MustacheTemplateEngine.instance() .render("meals.mustache", map); return Response.ok() .type(MediaType.TEXT_HTML) .entity(html) .build(); } @GET @Path("/{id}") @Produces({ "application/json" }) public Response meal(@PathParam("id") int id) { return Response.ok() .entity(mealService.find(id)) .build(); } }
5.4. Main Program
In the Spring scenario, this is how we get the microservice started:
public class Application { public static void main(String[] args) { MSF4JSpringApplication.run(Application.class, args); } }
Once started, we can see the result at http://localhost:8080/meals. The default port differs in Spring projects, but we can set it to whatever port we want.
5.5. Configuration Beans
To enable specific settings, including interceptors and session management, we can add configuration beans.
For example, this one changes the default port for the microservice:
@Configuration public class PortConfiguration { @Bean public HTTPTransportConfig http() { return new HTTPTransportConfig(9090); } }
6. Conclusion
In this article, we’ve introduced the MSF4J framework, applying different scenarios to build Java-based microservices.
There is a lot of buzz around this concept, but some theoretical background has been already set, and MSF4J provides a convenient and standardized way to apply this pattern.
Also, for some further reading, take a look at building Microservices with Eclipse Microprofile, and of course our guide on Spring Microservices with Spring Boot and Spring Cloud.
And finally, all the examples here can be found in the GitHub repo.