In the tutorial, we show how to Producer/Consumer data from ActiveMQ with Angular 9 & SpringBoot RestAPIs.
Related posts:
– ActiveMQ Producer/Consumer + SpringBoot RestAPIs example
– RabbitMq – How to create Spring RabbitMq Publish/Subcribe pattern with SpringBoot
– How to use Spring Kafka JsonSerializer (JsonDeserializer) to produce/consume Java Object messages
Related Pages:
Technologies
- Java 1.8
- Maven 3.3.9
- Spring Tool Suite – Version 3.9.4.RELEASE
- Spring Boot: 2.0.3.RELEASE
- ActiveMQ
- Angular 9
Overview
We create a Spring JMS ActiveMQ with JMS Producer & JMS Consumer as below:
Then expose RestAPIs to POST/GET data to/from ActiveMQ:
@PostMapping(value="/api/task")
@GetMapping(value="/api/tasks")
Use Angular Client to submit/get data from ActiveMQ via above RestAPI:
ActiveMQ state:
Practice
SpringBoot Backend
Setup SpringBoot project
Use SpringToolSuite to create a SpringBoot project with below dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
ActiveMQ Connection Factory
ActiveMqConnectionFactoryConfig
->
package com.ozenero.activemq.config;
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
@Configuration
public class ActiveMqConnectionFactoryConfig {
@Value("${gkz.activemq.broker.url}")
String brokerUrl;
@Value("${gkz.activemq.borker.username}")
String userName;
@Value("${gkz.activemq.borker.password}")
String password;
/*
* Initial ConnectionFactory
*/
@Bean
public ConnectionFactory connectionFactory(){
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(brokerUrl);
connectionFactory.setUserName(userName);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean // Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
/*
* Used for Receiving Message
*/
@Bean
public JmsListenerContainerFactory> jsaFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setMessageConverter(jacksonJmsMessageConverter());
configurer.configure(factory, connectionFactory);
return factory;
}
/*
* Used for Sending Messages.
*/
@Bean
public JmsTemplate jmsTemplate(){
JmsTemplate template = new JmsTemplate();
template.setMessageConverter(jacksonJmsMessageConverter());
template.setConnectionFactory(connectionFactory());
return template;
}
}
Add ActiveMQ configuration in application.properties
->
gkz.activemq.broker.url=tcp://localhost:61616
gkz.activemq.borker.username=admin
gkz.activemq.borker.password=admin
gkz.activemq.queue=gkz-queue
Data Model
– Create Task model ->
package com.ozenero.activemq.model;
public class Task {
private Long id;
private String name;
public Task(){
}
public Task(Long id, String name){
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
– Create MessageStorage
to storage Task
list ->
package com.ozenero.activemq.model;
import java.util.ArrayList;
import java.util.List;
public class MessageStorage {
private List tasks = new ArrayList();
public void add(Task task) {
tasks.add(task);
}
public void clear() {
tasks.clear();
}
public List getAll(){
return tasks;
}
}
Create a bean for MessageStorage
->
package com.ozenero.activemq.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ozenero.activemq.model.MessageStorage;
@Configuration
public class BeanConfiguration {
@Bean
public MessageStorage customerStorage() {
return new MessageStorage();
}
}
JMS Producer
JmsProducer
send messages to ActiveMQ ->
package com.ozenero.activemq.jms.producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
import com.ozenero.activemq.model.Task;
@Component
public class JmsProducer {
@Autowired
JmsTemplate jmsTemplate;
@Value("${gkz.activemq.queue}")
String queue;
public void send(Task task){
jmsTemplate.convertAndSend(queue, task);
}
}
JMS Consumer
JmsConsumer
recieves messages from ActiveMQ ->
package com.ozenero.activemq.jms.consumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import com.ozenero.activemq.model.MessageStorage;
import com.ozenero.activemq.model.Task;
@Component
public class JmsConsumer {
@Autowired
private MessageStorage taskStorage;
@JmsListener(destination = "${gkz.activemq.queue}", containerFactory="jsaFactory")
public void receive(Task task){
taskStorage.add(task);
}
}
Rest APIs
RestAPI
->
package com.ozenero.activemq.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ozenero.activemq.jms.producer.JmsProducer;
import com.ozenero.activemq.model.MessageStorage;
import com.ozenero.activemq.model.Task;
@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class RestAPIs {
@Autowired
JmsProducer jmsProducer;
@Autowired
private MessageStorage taskStorage;
@PostMapping(value="/api/task")
public Task postCustomer(@RequestBody Task task){
jmsProducer.send(task);
return task;
}
@GetMapping(value="/api/tasks")
public List getAll(){
List tasks = new ArrayList(taskStorage.getAll());
taskStorage.clear();
return tasks;
}
}
Angular Frontend
Setup Angular Project
Setup guide:
- Create Angular project with commandline:
ng new angular6-client
- Generate
Task
model with commandlineng generate class Task
- Generate
TaskService
with commandlineng generate service Task
- Generate
TaskComponent
with commandlineng generate component Task
Then install Bootstrap by commandline ->
>npm install bootstrap jquery --save
Configure installed Bootstrap & JQuery in angular.json
file ->
...
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
...
Data Model
Task
->
export class Task {
id: number;
name: string;
}
Implement HttpClient Service
TaskService
->
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Task } from './task';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({
providedIn: 'root'
})
export class {
constructor(
private http: HttpClient
) { }
getTasks (): Observable {
return this.http.get("http://localhost:8080/api/tasks")
}
addTask (task: Task): Observable {
return this.http.post("http://localhost:8080/api/task", task, httpOptions);
}
}
Implement ActiveMQ Component
activemq-task.component.html
->
<div [hidden]="submitted">
<h3>Add Task</h3>
<form #addTaskForm="ngForm">
<div class="form-group">
<label for="id">Id</label>
<input type="number" class="form-control" id="id"
placeholder="Enter Id"
required
[(ngModel)]="task.id" name="id" #id="ngModel">
<div [hidden]="id.valid || id.pristine"
class="alert alert-danger">
Id is required
</div>
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" placeholder="Enter Task Name"
required
[(ngModel)]="task.name" name="name" #name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Name is required
</div>
</div>
<button class="btn btn-dark" (click)="addTask()" [disabled]="!addTaskForm.form.valid">Add Task</button>
</form>
</div>
<div [hidden]="!submitted">
<p>Submitted Successfully! -> <span class="badge badge-dark">Task's Info -> Id: {{task.id}}, Name: {{task.name}}</span></p>
<div class="btn-group btn-group-sm">
<button class="btn btn-secondary" (click)="newTask(); addTaskForm.reset();">New Task</button>
<button class="btn btn-secondary" (click)="processTasks();">Process Tasks</button>
</div>
<div [hidden]="!processing">
<br>
<h5>Processing</h5>
<ul>
<li *ngFor="let task of tasks">
Task id = {{task.id}}, name = {{task.name}}
</li>
</ul>
</div>
</div>
– activemq-task.component.ts
->
import { Component, OnInit } from '@angular/core';
import { Task } from '../task';
import { TaskService } from '../task.service';
@Component({
selector: 'app-activemq-task',
templateUrl: './activemq-task.component.html',
styleUrls: ['./activemq-task.component.css']
})
export class ActivemqTaskComponent{
task = new Task();
tasks: Task[];
submitted = false;
processing = false;
constructor(private taskService: TaskService) { }
newTask(): void {
this.submitted = false;
this.processing = false;
this.task = new Task();
}
addTask() {
this.submitted = true;
this.taskService.addTask(this.task)
.subscribe();
}
processTasks(){
this.processing = true;
return this.taskService.getTasks()
.subscribe(
tasks => {
console.log(tasks);
this.tasks = tasks;
}
);
}
}
– Create style file assets/forms.css
->
.ng-valid[required], .ng-valid.required {
border-left: 5px solid rgba(32, 77, 32, 0.623);
}
.ng-invalid:not(form) {
border-left: 5px solid rgb(148, 27, 27);
}
– Add above style file assets/forms.css
to index.html
file ->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular6Client</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="assets/forms.css">
</head>
<body>
<app-root></app-root>
</body>
</html>
– Add app-activemq-task
selector to app.component.html
file ->
<div class="container">
<div class="row">
<div class="col-sm-4">
<app-activemq-task></app-activemq-task>
</div>
</div>
</div>
Run & Check Results
– Build & Run SpringBoot project with commandlines {mvn clean install
, mvn spring-boot:run
}.
– Run the Angular project as commandline: ng serve
Add Task ->
Get Tasks ->
ActiveMQ state ->
SourceCode
– SpringBootRestAPIsActiveMQ
– Angular6-Client
Could you pls provide the article on how to implement transaction in spring boot activemq…
615463 792488This website is often a walk-through like the information you wanted in regards to this and didnt know who to question. Glimpse here, and you will undoubtedly discover it. 168031
You made some decent points there. I did a search on the subject matter and found most persons will approve with your site.
I have been exploring for a little bit for any high quality articles or blog posts in this sort of space . Exploring in Yahoo I eventually stumbled upon this web site. Studying this info So i am happy to express that I’ve an incredibly just right uncanny feeling I found out just what I needed. I such a lot for sure will make sure to do not fail to remember this site and provides it a look a relentless basis.
well, there are so many tourist attractions that you find on asia and europe. i would really love to travel a lot::
I think other web-site proprietors should take this website as an model, very clean and excellent user friendly style and design, as well as the content. You’re an expert in this topic!
Audio began playing when I opened up this web site, so annoying!
Your blog is amazing dude. i love to visit it everyday. very nice layout and content “
Nice Post. It’s really a very good article. I noticed all your important points. Thanks!!
Keep an eye on this one, as it is one of the best summer surprises in recent years.
232860 6568some genuinely choice content on this internet website , saved to my bookmarks . 252927
Nice post. I understand something much harder on diverse blogs everyday. Most commonly it is stimulating to learn to read content off their writers and employ a little something from their site. I’d opt to use some while using content on my own weblog whether you do not mind. Natually I’ll provide link in your internet blog. Many thanks sharing.
677107 929269This web-site can be a walk-through rather than the info you wished about it and didnt know who ought to. Glimpse here, and youll definitely discover it. 606154
Hello there! This post couldn’t be written any better! Reading this post
reminds me of my old room mate! He always kept talking about this.
I will forward this article to him. Fairly certain he will have a good read.
Many thanks for sharing!
We are a group of volunteers and opening a new scheme in our
community. Your web site provided us with valuable information to work on. You have done
an impressive job and our whole community will be thankful
to you.
My brother suggested I may like this blog.
He was once totally right. This submit actually made my
day. You can not imagine just how a lot time I had spent for this info!
Thanks!
I all the time emailed this webpage post page to all my friends,
as if like to read it then my links will too.
My brother suggested I might like this website. He was totally right.
This post actually made my day. You cann’t imagine just how much time I
had spent for this information! Thanks!
This site certainly has all of the information and
facts I needed about this subject and didn’t know who to ask.
Thanks for your personal marvelous posting! I quite enjoyed reading it, you might be a great author.I will be sure to bookmark your blog
and may come back in the future. I want to encourage you continue your great job, have a nice afternoon!
A motivating discussion is definitely worth comment.
I think that you ought to publish more about this topic,
it might not be a taboo matter but generally people do
not speak about these subjects. To the next!
All the best!!
I am not sure where you’re getting your information, but great
topic. I needs to spend some time learning more
or understanding more. Thanks for great info I was looking for this info for my mission.
I’m extremely impressed together with your writing skills and also with
the structure to your blog. Is that this
a paid theme or did you modify it yourself? Anyway keep up the nice quality
writing, it’s uncommon to see a great weblog like this
one nowadays..
Hey there! I’ve been reading your blog for a long time now
and finally got the courage to go ahead and give you a shout
out from Porter Texas! Just wanted to tell you keep up the excellent
job!