DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Aggregating REST APIs Calls Using Apache Camel
  • Spring Boot Microservices + Apache Camel: A Hello World Example
  • Spring Microservices RESTFul API Documentation With Swagger Part 1
  • How to Develop Microservices With Spring Cloud and Netflix Discovery

Trending

  • How to Practice TDD With Kotlin
  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  • A Deep Dive Into Firmware Over the Air for IoT Devices
  • How to Configure and Customize the Go SDK for Azure Cosmos DB
  1. DZone
  2. Coding
  3. Frameworks
  4. REST Services With Apache Camel

REST Services With Apache Camel

Apache Camel can be run anywhere as a standalone or embedded as a library, and it aids integration. Read on to learn how to use it to expose REST services.

By 
Praveen KG user avatar
Praveen KG
·
Oct. 18, 21 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
29.4K Views

Join the DZone community and get the full member experience.

Join For Free

Microservices are becoming a very popular architectural style for developing greenfield applications and also for brownfield solutions. People are moving away from the monolith solutions due to added advantages like faster development and go-to-market, increased adoption of containerization and small teams, and a lighter codebase. 

You can use either Spring Boot, Quarkus, or Lagom frameworks to develop the REST services. I would like to show how we can use Apache Camel, a leading opensource integration framework, to write REST services easier and quicker using the REST domain-specific language (DSL).

Camel is a Java-based implementation of Enterprise Integration Patterns (EIPs) that supports most of the EIP design patterns and newer integration patterns from microservice architecture.

Apache Camel can be run anywhere as a standalone and also embedded as a library within Spring Boot, Quarkus, Application Servers, and in the clouds. 

Apache Camel helps to integrate with everything by supporting hundreds of components that are used to access databases, message queues, and APIs.

How to Use Apache Camel to Expose REST Service

The Camel REST allows the creation of REST services using Restlet, Servlet, and many such HTTP-aware components for implementation.

As you all know, Camel's main feature is the routing engine. Routes can be developed using either Java-based DSL or XML-based. In this article, I will follow the Java DSL to develop a REST service.

Defining Endpoints

To define the endpoints, we need to use the Apache Camel DSL with Java DSL (although you can use XML).  

Java DSL is below:

Java
 
rest("/api/products")
     .get().route().to("...")
     .post().route().to("...")
     .delete().route().to("...");

It is similar to the Camel route but uses rest(). We need to mention the component services use to expose the endpoint. Camel supports the below components to Bootstrap REST service implementation:

  • Servlet
  • Spark REST
  • Netty HTTP
  • Jetty

If you are planning to integrate Camel with Spring Boot framework to expose the services, it's better to use the servlet component because Spring Boot supports embedded Tomcat, which Camel can use.

Let's configure the REST configuration as:

Java
 
// Define the implementing component - and accept the default host and port
restConfiguration()
  .component("servlet");

How to Override the Port

You can override the default port 8080 with any other port number of your choice either by setting the .port() to restConfiguration() API or, if you integrated the Apache Camel with Spring Boot, you can use the server.port=8082 in application.properties.

Override the Context Path

By default, Camel maps imports requests to /camel/*. You can override it to any specific path of your choice by using the application.properties as camel.component.servlet.mapping.context-path=/services/api/*.

Configure the binding mode to marshal the request to the POJO object. If set to anything other than "off," the producer will try to convert the body of the incoming message from inType to the JSON or XML, and the response from JSON or XML to outType. There are five enums and the value can be one of the following: auto, off, JSON, XML, or json_xml. To achieve this,  you need to set the binding mode to restConfiguration() as bindingMode(RestBindingMode.auto);. 

Take a look at the sample configuration of REST API below:

Java
 

@Component
public class HttpRouteBuilder extends BaseRouteBuilder {

	@Override
	public void configure() throws Exception {
		super.configure();

		// it tells Camel how to configure the REST service
		restConfiguration()
				// Use the 'servlet' component.
				// This tells Camel to create and use a Servlet to 'host' the RESTful API.
				// Since we're using Spring Boot, the default servlet container is Tomcat.
				.component("servlet")
				// Allow Camel to try to marshal/unmarshal between Java objects and JSON
				.bindingMode(RestBindingMode.auto);

		rest().get("/kyc/{uid}").route().process("httpRequestProcessor").to("log:?level=INFO&showBody=true").endRest();

		rest().post("/kyc").type(RequestObject.class).route().to("bean-validator:myvalidatorname")
				.process("httpRequestProcessor").to("log:?level=INFO&showBody=true");

	}

}


You can validate your incoming request using the Apache Camel bean validator component which requires the camel-bean-validator dependency to be added to your Maven POM.

XML
 
<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-bean-validator</artifactId>
</dependency>


Define Validation Rules in Request Object

To implement input request validation, you need to add validation annotations to fields in your POJO/request class. These are available in the package javax.validation.constraints. The most common ones from the JSR-303 API are:

  • @NotNull — checks that the field is not null
  • @AssertTrue/@AssertFalse — checks that the field is true or false
  • @Pattern(regex=, flags=) — checks that the field matches the given regex, with the given flags

There are some Hibernate-specific annotations in org.hibernate.validator.constraints, like:

  • @Email — checks that the field contains a valid email address
  • @CreditCardNumber — this one’s probably obvious
  • @NotEmpty — checks whether the annotated field is not null nor empty

How to Handle Exceptions

You can handle different types of exceptions and send the custom error messages to the client using the Apache Camel exception clause (onException) either at route level or at the global level. You can also override the response HTTP code and message for the REST API calls.

Java
 
public class BaseRouteBuilder extends RouteBuilder {

	@Override
	public void configure() throws Exception {
		onException(BeanValidationException.class).handled(true).process(new Processor() {

			@Override
			public void process(Exchange exchange) throws Exception {
				Throwable cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);

				exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
				exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
				exchange.getMessage().setBody("{error:" + cause.getMessage() + "}");

			}
		});

		onException(InvalidRequestException.class).handled(true).process(new Processor() {

			@Override
			public void process(Exchange exchange) throws Exception {
				Throwable cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
				exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
				exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
				exchange.getMessage().setBody("{error:" + cause.getMessage() + "}");

			}
		});

		onException(Exception.class).handled(true).process(new Processor() {

			@Override
			public void process(Exchange exchange) throws Exception {
				Throwable cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
				exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 500);
				exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
				exchange.getMessage().setBody("{error:" + cause.getMessage() + "}");

			}
		});
}

Note: Here I created a base class to handle all sorts of exceptions, and in my main REST API builder class (HttpRouteBuilder), it extends BaseRouteBuilder.

Finally, POM: 

XML
 
<dependencyManagement>
		<dependencies>
			<!-- Spring Boot BOM -->
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>${spring-boot.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<!-- Camel BOM -->
			<dependency>
				<groupId>org.apache.camel.springboot</groupId>
				<artifactId>camel-spring-boot-dependencies</artifactId>
				<version>${camel.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.projectlombok</groupId>
				<artifactId>lombok</artifactId>
				<version>1.18.20</version>
				<scope>provided</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
			<exclusions>
				<exclusion>
					<groupId>com.fasterxml.jackson.datatype</groupId>
					<artifactId>jackson-datatype-jsr310</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.fasterxml.jackson.core</groupId>
					<artifactId>jackson-annotations</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>com.fasterxml.jackson.datatype</groupId>
					<artifactId>jackson-datatype-jsr310</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-spring-boot-starter</artifactId>

		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-jackson-starter</artifactId>
			<exclusions>
				<exclusion>
					<groupId>com.fasterxml.jackson.core</groupId>
					<artifactId>jackson-annotations</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.camel.springboot</groupId>
			<artifactId>camel-servlet-starter</artifactId>
		</dependency>
		<!-- Testing Dependencies -->
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test-spring</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>com.vaadin.external.google</groupId>
					<artifactId>android-json</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-swagger-java</artifactId>

		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-bean-validator</artifactId>
		</dependency>
	</dependencies>


Summary

Now that you know how to expose REST API with Camel, you might be wondering when/why you should use Apache Camel to build REST services. The simple answer is if you are already using Apache Camel to integrate the data between different protocols and applications, then REST is another data source you need to support instead of building REST services with Spring Boot or any other framework. You can utilize the Camel REST component to expose REST API and to consume/produce messages using known Camel DSL, which helps you to standardize the technical stake. You can also extend the Camel REST to include Swagger for providing the API specification using the camel-swagger component.

REST Web Protocols Apache Camel microservice Spring Framework Domain-Specific Language

Opinions expressed by DZone contributors are their own.

Related

  • Aggregating REST APIs Calls Using Apache Camel
  • Spring Boot Microservices + Apache Camel: A Hello World Example
  • Spring Microservices RESTFul API Documentation With Swagger Part 1
  • How to Develop Microservices With Spring Cloud and Netflix Discovery

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!