All I know about Spring as a Spring Boot app

Overview

All about Spring

This repository contains all the knowledge I have and all the things I can do with Spring

You can download v1.0.0 java-doc here

In this repository, a spring boot application has been implemented that has a registration and login system. After logging in, you can use a public chat system that sends your message to all online sessions. You can also view and reply to messages from other sessions.

The online users' box system and private chat will be implemented in the next version.

Functionalities that implemented in version one

Spring Security and JWT Authorization

To implement Spring Security settings, the SecurityConfig extends WebSecurityConfigurerAdapter and it's filter JwtRequestFilter extends OncePerRequestFilter is required to implement.

(Security settings can also be done via the XML file, You can read docs or this tutorial)

The settings I have done for my application are such that all the requests that reach the server hit a filter before the controllers. If they are authenticated by jwt, they reach the controllers, otherwise the code 403 is returned to them.

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().exceptionHandling().and()
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
	http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

Paths defined in the

@Override
public void configure(WebSecurity web) throws Exception {
	web.ignoring().antMatchers("/", "/api/signup", "/authenticate", "/connect/**", "/lib/**");
}

in the SecurityConfig class and the

private static List<String> skipFilterUrls = Arrays.asList("/", "/api/signup", "/authenticate", "/connect/**", "/lib/**");

@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
	return skipFilterUrls.stream().anyMatch(url -> new AntPathRequestMatcher(url).matches(request));
}

in the JwtRequestFilter are ignored for authentication and hits the controllers.

  • "/" is for index page.
  • "/api/signup" is for signup POST request.
  • "/authenticate" is a POST path for authenticate users and assign jwt to them.
  • "/connect/**" is for WebSocket.
  • "/lib/**" is for Stomp client js files.

Spring Rest Service

To implement a rest service system, a class must be implemented as a controller and receive requests for a URL path using @PostMapping(path = "<PATH>", produces = MediaType.APPLICATION_JSON_VALUE) annotation.

@RestController
@RequestMapping("/api")
public class APIController {

	@PostMapping(path = "<PATH>", produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<?> signup(@CookieValue(value = "JSESSIONTOKEN", defaultValue = "null") String jwt,
			HttpServletRequest request, @RequestBody String payload) {
		return new ResponseEntity<String>(<RESPONSE>, HttpStatus.OK);
	}
  
}
  • @RestController and @RequestMapping("<PRIFIX>") are annotions for Rest controller's class. <PRIFIX> Is a path that comes before api path's.
  • @CookieValue(value = "JSESSIONTOKEN", defaultValue = "null") String jwt Is for JWT in client Cookie.
  • HttpServletRequest request Is for client Information.
  • @RequestBody String payload Is the body of request.
  • Returns new ResponseEntity<String>(<RESPONSE>, HttpStatus.OK) as response to client. <RESPONSE> Is an object that returns to client. HttpStatus.OK the status code of response to client.

Thymleaf

To implement Thymleaf template engine, a class must be implemented as a controller and receive requests for a URL path using @RequestMapping(<PATH>) anotation.

@Controller
public class ResourceController {

	@RequestMapping("/")
	public String index(@CookieValue(value = "JSESSIONTOKEN", defaultValue = "null") String jwt,
			HttpServletRequest request, Model model) {
		return "index";
	}

}
  • @CookieValue(value = "JSESSIONTOKEN", defaultValue = "null") String jwt Is for JWT in client Cookie.
  • HttpServletRequest request Is for client Information.
  • Model model Is for Thymleaf template engine.
  • Returns name of html file palced in src/main/resources/templates/ that we want to return to the client.

Spring WebSocket and Session

Server side

The first thing to do is to enable the WebSocket capabilities. To do this we need to add a configuration to our application and annotate this class with @EnableWebSocketMessageBroker.

As its name suggests, it enables WebSocket message handling, backed by a message broker:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		config.enableSimpleBroker(SocketEndpoints.SUBSCRIBE_QUEUE, SocketEndpoints.SUBSCRIBE_USER_REPLY);
		config.setUserDestinationPrefix(SocketEndpoints.SUBSCRIBE_USER_PREFIX);
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint(SocketEndpoints.ENDPOINT_CONNECT, SocketEndpoints.ENDPOINT_USER)
				.setHandshakeHandler(new AssignPrincipalHandshakeHandler()).setAllowedOriginPatterns("*").withSockJS();
	}

}

I implement the constatnts in SocketEndpoints class:

public class SocketEndpoints {
	public static final String SUBSCRIBE_USER_PREFIX = "/private";
	public static final String SUBSCRIBE_USER_REPLY = "/reply";
	public static final String SUBSCRIBE_QUEUE = "/queue";
	public static final String ENDPOINT_CONNECT = "/connect";
	public static final String ENDPOINT_USER = "/user";
}

Here, we can see that the method configureMessageBroker is used to configure the message broker. First, we enable an in-memory message broker to carry the messages back to the client on destinations prefixed with "/reply".

The "/queue" prefix is for public messaging. The messages that the server puts on this path are sent to all the clients that are subscribed on this path.

We complete our configuration by designating the "/private" prefix to filter destinations targeting application annotated methods (via @MessageMapping). The registerStompEndpoints method registers the "/connect" and "/user" endpoint, enabling Spring’s STOMP support.

It also enables the SockJS fallback options, so that alternative messaging options may be used if WebSockets are not available. This is useful since WebSocket is not supported in all browsers yet and may be precluded by restrictive network proxies.

The fallbacks let the applications use a WebSocket API but gracefully degrade to non-WebSocket alternatives when necessary at runtime.

To assign a session to each client, A hand shake handler implement in AssignPrincipalHandshakeHandler class, That gives a session as JSESSIONID in client's Cookie before the web socket establish between the client and server.

public class AssignPrincipalHandshakeHandler extends DefaultHandshakeHandler {
	private static final String ATTR_PRINCIPAL = "__principal__";

	@Override
	protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
			Map<String, Object> attributes) {
		final HttpSession session;
		ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
		session = servletRequest.getServletRequest().getSession();
		attributes.put(ATTR_PRINCIPAL, session.getId());
		return new Principal() {
			@Override
			public String getName() {
				return session.getId();
			}
		};
	}

}

To handle web socket events, a EventHandler class is imlemented that listens to we socket events using @EventListener annotation to log them.

@Configuration
public class EventHandler {

	private static Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

	@EventListener
	public void handleSubscribeEvent(SessionSubscribeEvent event) {
		log.info("<==> handleSubscribeEvent: session=" + event.getUser().getName() + ", event=" + event);
	}

	@EventListener
	public void handleConnectEvent(SessionConnectEvent event) {
		log.info("===> handleConnectEvent: session=" + event.getUser().getName() + ", event=" + event);
	}

	@EventListener
	public void handleDisconnectEvent(SessionDisconnectEvent event) {
		log.info("<=== handleDisconnectEvent: session=" + event.getUser().getName() + ", event=" + event);
	}
}

As I said above, To send a message through the web socket, There are two ways of private and public sending, Which private way is for send messages to a specific session, and public way is for sending messages to all sessions that have subscribed.

With the convertAndSend method, the message is sent to an endpoint that has been seted as the public message path (in my code is "/queue") and all sessions that subscribe to this endpoint will receive it.

messagingTemplate.convertAndSend(SocketEndpoints.SUBSCRIBE_QUEUE + "/public", <RESPONSE>);

The convertAndSendToUser method is for sending a private message to a specific session and gets the desired client session and the predefined private message path and the message as arguments.

messagingTemplate.convertAndSendToUser(session, Constants.SUBSCRIBE_USER_REPLY, <RESPONSE>);

Client side

First of all, you need to provide the web socket and stomp libraries for the client. download here

In the following code snippet, the client first requests a connection to the specified path for the web socket, which is the "/connect", And if a connection is established, Stomp protocol sits on the connection. Finally, The client subscribes to private and public message paths and pass incoming messages to the responseHandler function to be handled.

window.onload = function() {
	var socket = new SockJS(location.protocol + "//" + location.host
        	+ "/connect");
        stompClient = Stomp.over(socket);
        stompClient.debug = null;
        stompClient.connect({}, function(frame) {
        	stompClient.subscribe('/private/reply', function(notification) {
                	responseHandler(notification.body);
                });
                stompClient.subscribe('/queue/public', function(notification) {
                        responseHandler(notification.body);
                });
         });
}

function responseHandler(data) {
	console.log(data);
}
You might also like...

This repo contains all the materials for placement as well as Practical lab codes for all subjects and notes. For students graduating in 2023

UEMK_PLACEMENT_2023 This repo contains all the materials for placement as well as Practical lab codes for all subjects and notes. For students graduat

Mar 5, 2022

Spring Boot Login and Registration example with MySQL, JWT, Rest Api - Spring Boot Spring Security Login example

Spring Boot Login and Registration example with MySQL, JWT, Rest Api - Spring Boot Spring Security Login example

Spring Boot Login example with Spring Security, MySQL and JWT Appropriate Flow for User Login and Registration with JWT Spring Boot Rest Api Architect

Jan 5, 2023

tuya-spring-boot-starter helps you efficiently create cloud development projects regarding the OpenAPI or message subscription capabilities. You can put all the focus on business logic without taking care of server-side programming nor relational databases.

English | 中文版 tuya-spring-boot-starter helps you efficiently create cloud development projects regarding the OpenAPI or message subscription capabilit

Dec 26, 2022

about learning Spring Boot via examples. Spring Boot 教程、技术栈示例代码,快速简单上手教程。

about learning Spring Boot via examples. Spring Boot 教程、技术栈示例代码,快速简单上手教程。

Spring Boot 学习示例 Spring Boot 使用的各种示例,以最简单、最实用为标准,此开源项目中的每个示例都以最小依赖,最简单为标准,帮助初学者快速掌握 Spring Boot 各组件的使用。 Spring Boot 中文索引 | Spring Cloud学习示例代码 | Spring

Jan 1, 2023

spring boot 实践学习案例,是 spring boot 初学者及核心技术巩固的最佳实践。另外写博客,用 OpenWrite。

spring boot 实践学习案例,是 spring boot 初学者及核心技术巩固的最佳实践。另外写博客,用 OpenWrite。

推荐工具: 微信公众号 Markdown 编辑器 - OpenWrite:Markdown 微信编辑器是一款专业强大的微信公众平台在线编辑排版工具,提供手机预览功能,让用户在微信图文 、文章、内容排版、文本编辑、素材编辑上更加方便。 - 更多介绍 博客群发平台 一、支持泥瓦匠 Spring Boot

Jan 5, 2023

Spring-Boot-Plus is a easy-to-use, high-speed, high-efficient,feature-rich, open source spring boot scaffolding

Spring-Boot-Plus is a easy-to-use, high-speed, high-efficient,feature-rich, open source spring boot scaffolding

Everyone can develop projects independently, quickly and efficiently! What is spring-boot-plus? A easy-to-use, high-speed, high-efficient, feature-ric

Dec 31, 2022

Two Spring-boot applications registering themselves to an spring-boot-admin-server application as separate clients for the purpose of monitoring and managing the clients

Two Spring-boot applications registering themselves to an spring-boot-admin-server application as separate clients for the purpose of monitoring and managing the clients

Spring-boot-admin implementation with 1 Server and 2 clients Creating a Server application to monitor and manage Spring boot applications (clients) un

Dec 6, 2022

Spring Boot Migrator (SBM) - a tool for automated code migrations to upgrade or migrate to Spring Boot

Spring Boot Migrator (SBM) - a tool for automated code migrations to upgrade or migrate to Spring Boot

Spring Boot Migrator uses and is compatible to OpenRewrite, a powerful mass refactoring ecosystem for Java and other source code.

Jan 2, 2023

Spring Boot Jhipster Photo Gallery App

Spring Boot Jhipster Photo Gallery App

Spring Boot Jhipster Photo Gallery Example Prerequisites Docker 19.03+ Docker Compose 1.25+ Build Docker Image ./mvnw -Pprod jib:dockerBuild clean ver

Aug 20, 2021
Comments
  • just involving

    just involving

    deleted mongo-db from classpath cause no one is using it (yet?) intention: avoiding usage of HashMap and static calls to Application.java

    added application.yaml for H2 configuration mainly as an example added application.properties for predefined and not hardcoded constants app might use

    moved CSVParser from Application.java to CSVParser.java as a CommandLinerRunner

    other changes are made accordingly (because of Db replacement)

    opened by nort3x 1
  • Some Suggestions

    Some Suggestions

    To improve your repo, I suggest adding a CRUD (Create, Read, Update, Delete) scenario that includes all Controler, Service, Model, and persistence layers and corresponding best practices.

    Also, add Swagger for API documentation. (Better to have the latest version to support Open API)

    opened by M-Razavi 1
Releases(v1.0.0)
Owner
Soroush Mehrad
Full-Stack Developer | Artificial Intelligence researcher | B.Sc in Software Engineering
Soroush Mehrad
循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Batch、Spring Cloud、Spring Cloud Alibaba、Spring Security & Spring Security OAuth2,博客Spring系列源码:https://mrbird.cc

Spring 系列教程 该仓库为个人博客https://mrbird.cc中Spring系列源码,包含Spring Boot、Spring Boot & Shiro、Spring Cloud,Spring Boot & Spring Security & Spring Security OAuth2

mrbird 24.8k Jan 6, 2023
Spring Boot microservices app with Spring Cloud, Robust and resilient backend managing e-Commerce app

e-Commerce-boot μServices Important Note: This project's new milestone is to move The whole system to work on Kubernetes, so stay tuned. Introduction

Selim Horri 65 Dec 23, 2022
The Spring Boot Sample App on K8S has been implemented using GKE K8S Cluster, Spring Boot, Maven, and Docker.

gke-springboot-sampleapp ?? The Spring Boot Sample App on K8S has been implemented using GKE K8S Cluster, Spring Boot, Maven, and Docker. Usage To be

KYEONGMIN CHO 1 Feb 1, 2022
An implementation of a sample E-Commerce app in k8s. This online retail marketplace app uses Spring Boot, React, and YugabyteDB.

An implementation of a sample E-Commerce app in k8s. This online retail marketplace app uses Spring Boot, React, and YugabyteDB.

yugabyte 1 Oct 27, 2022
With react-native-update-in-app library you can easily implement in-app updates in your React Native app using CDN or any other file server

React Native In-App update With react-native-update-in-app library you can easily implement in-app updates in your React Native app using CDN or any o

Nepein Andrey 7 Dec 21, 2022
Ever wondered how a baloon feels in a dangerous place? Now you know.

Dont-Pop Description Ever wondered how a balloon feels in a dangerous place? Now you know. This game belongs to the category of Survival Games: the pl

Michele Ravaioli 9 Oct 24, 2022
This repository should serve as a guide to everybody who wants to study software and hardware for embedded systems but doesn't know where to start.

Roadmap to Embedded Engineering This repository should serve as a guide to anyone who wants to study software and hardware for embedded systems but do

Mateus Antonio da Silva 108 Jan 4, 2023
You know, for id

分布式系统中,全局唯一 ID 的生成是一个老生常谈但是非常重要的话题。随着技术的不断成熟,大家的分布式全局唯一 ID 设计与生成方案趋向于趋势递增的 ID,这篇文章将结合我们系统中的 ID 针对实际业务场景以及性能存储和可读性的考量以及优缺点取舍,进行深入分析。本文并不是为了分析出最好的 ID 生成

null 5 Jun 17, 2022
You want to go to a cafe but don't know where to go. Let cafe hub support you. Ok let's go

cafe-hub You want to go to a cafe but don't know where to go. Let cafe hub support you. Ok let's go Architecture: Domain Driven Design (DDD) LDM Insta

Khoa 1 Nov 12, 2022
@FengG0d 's Client, but he leave, I am the new owner, but, I don't know how to write Java, I need your help.

IKUN Client Help me I need help! The original Author was leave, but I don't know how to write a good client, I need Your help! to make a good IKun Cli

Chenken520 2 Sep 4, 2022