spring-boot-realworld-example-app
Example Spring codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld API spec.
Top Related Projects
ASP.NET Core backend implementation for RealWorld
Exemplary real world backend API built with Laravel
Quick Overview
The gothinkster/spring-boot-realworld-example-app is a Spring Boot implementation of the RealWorld backend API spec. It serves as a demonstration of how to build a real-world application using Spring Boot, following best practices and modern development techniques. This project is part of the larger RealWorld initiative, which aims to create exemplary fullstack applications across various tech stacks.
Pros
- Implements a comprehensive, real-world API specification
- Uses Spring Boot, a popular and well-supported framework for Java applications
- Follows best practices and modern development techniques
- Serves as an excellent learning resource for developers
Cons
- May be complex for beginners to understand all aspects of the implementation
- Requires knowledge of Java and Spring Boot ecosystem
- Limited documentation on project-specific implementation details
- May require updates to keep up with evolving Spring Boot versions and best practices
Code Examples
Here are a few code examples from the project:
- User registration endpoint:
@PostMapping("/users")
public ResponseEntity createUser(@Valid @RequestBody RegisterParam registerParam) {
User user = userService.createUser(registerParam);
UserWithToken userWithToken = userService.userWithToken(user);
return ResponseEntity.status(201).body(userWithToken);
}
This code defines a POST endpoint for user registration, validating the input and returning the created user with a token.
- Article creation:
@PostMapping("/articles")
public ResponseEntity createArticle(@Valid @RequestBody NewArticleParam newArticleParam,
@AuthenticationPrincipal User currentUser) {
Article article = articleService.createArticle(newArticleParam, currentUser);
return ResponseEntity.status(201).body(articleResponse(article));
}
This code handles the creation of a new article, using the authenticated user as the author.
- JWT authentication filter:
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(request);
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
}
This code implements a JWT token filter for authentication, validating the token and setting the authentication context.
Getting Started
To get started with this project:
-
Clone the repository:
git clone https://github.com/gothinkster/spring-boot-realworld-example-app.git
-
Navigate to the project directory:
cd spring-boot-realworld-example-app
-
Build and run the application:
./gradlew bootRun
-
The API will be available at
http://localhost:8080/api
For more detailed instructions and API documentation, refer to the project's README file.
Competitor Comparisons
Pros of node-express-realworld-example-app
- Lightweight and faster development due to JavaScript's simplicity
- Larger ecosystem of npm packages for quick feature implementation
- Non-blocking I/O model for better performance in high-concurrency scenarios
Cons of node-express-realworld-example-app
- Less robust type checking compared to Java's static typing
- Potential for callback hell in asynchronous operations
- Lack of built-in multithreading support for CPU-intensive tasks
Code Comparison
node-express-realworld-example-app:
router.post('/users', async (req, res, next) => {
try {
const user = await User.create(req.body.user);
return res.json({user: user.toAuthJSON()});
} catch(error) {
return next(error);
}
});
spring-boot-realworld-example-app:
@PostMapping("/users")
public ResponseEntity<UserResponse> createUser(@Valid @RequestBody NewUserRequest newUserRequest) {
User user = userService.createUser(newUserRequest);
return ResponseEntity.status(HttpStatus.CREATED)
.body(UserResponse.fromUserAndToken(user, jwtService.toToken(user)));
}
The Node.js example uses async/await for handling asynchronous operations, while the Spring Boot example utilizes Java's synchronous approach with built-in validation annotations. The Spring Boot version provides more explicit type definitions and HTTP status handling.
ASP.NET Core backend implementation for RealWorld
Pros of aspnetcore-realworld-example-app
- Built on ASP.NET Core, offering excellent performance and cross-platform compatibility
- Utilizes Entity Framework Core for efficient database operations
- Implements a clean architecture with separation of concerns
Cons of aspnetcore-realworld-example-app
- Less extensive community support compared to Spring Boot ecosystem
- Fewer third-party libraries and integrations available
- Steeper learning curve for developers not familiar with .NET ecosystem
Code Comparison
spring-boot-realworld-example-app:
@GetMapping("/articles/{slug}")
public ResponseEntity<SingleArticleResponse> getArticle(@PathVariable("slug") String slug) {
return articleQueryService.findBySlug(slug)
.map(article -> ResponseEntity.ok(SingleArticleResponse.fromArticle(article)))
.orElseThrow(ResourceNotFoundException::new);
}
aspnetcore-realworld-example-app:
[HttpGet("{slug}")]
public async Task<IActionResult> Get(string slug)
{
var article = await _articleRepository.GetArticleBySlug(slug);
if (article == null)
return NotFound();
return Ok(new { article = _mapper.Map<ArticleResponse>(article) });
}
Both implementations handle article retrieval by slug, but the ASP.NET Core version uses async/await for better scalability. The Spring Boot version uses Java 8 Optional for null handling, while the ASP.NET Core version checks for null explicitly.
Exemplary real world backend API built with Laravel
Pros of laravel-realworld-example-app
- Simpler setup and configuration due to Laravel's convention-over-configuration approach
- Built-in support for authentication and authorization using Laravel's native features
- More extensive documentation and larger community support for Laravel
Cons of laravel-realworld-example-app
- Less scalable for large, enterprise-level applications compared to Spring Boot
- Potentially slower performance, especially under high load, due to PHP's interpreted nature
- Limited options for microservices architecture compared to Spring Boot's ecosystem
Code Comparison
Laravel (PHP):
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
return $this->respondWithToken(Auth::user()->generateToken());
}
return response()->json(['error' => 'Unauthorized'], 401);
}
Spring Boot (Java):
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getEmail(), loginRequest.getPassword())
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtTokenProvider.generateToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
}
The Laravel example showcases its simplicity in handling authentication, while the Spring Boot example demonstrates its more verbose but flexible approach to security and token generation.
Pros of django-realworld-example-app
- Simpler and more lightweight framework, easier to set up and get started
- Better suited for smaller to medium-sized projects
- More flexibility in architectural choices and design patterns
Cons of django-realworld-example-app
- Less robust for large-scale enterprise applications compared to Spring Boot
- Fewer built-in features and integrations out of the box
- Potentially slower performance for high-traffic applications
Code Comparison
Django (django-realworld-example-app):
class ArticleViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
lookup_field = 'slug'
queryset = Article.objects.select_related('author', 'author__user')
permission_classes = (IsAuthenticatedOrReadOnly,)
serializer_class = ArticleSerializer
Spring Boot (spring-boot-realworld-example-app):
@RestController
@RequestMapping(path = "/articles")
class ArticleController {
private final ArticleRepository articleRepository;
private final UserRepository userRepository;
@GetMapping
public ResponseEntity<?> getArticles(@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "20") int limit) {
return ResponseEntity.ok(articleRepository.findAll(new PageRequest(offset, limit)));
}
}
Both examples showcase the implementation of article-related functionality, with Django using a ViewSet approach and Spring Boot using a RestController. The Django code appears more concise, while the Spring Boot code offers more explicit request mapping and dependency injection.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Spring boot + MyBatis codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.
This codebase was created to demonstrate a fully fledged full-stack application built with Spring boot + Mybatis including CRUD operations, authentication, routing, pagination, and more.
For more information on how to this works with other frontends/backends, head over to the RealWorld repo.
NEW GraphQL Support
Following some DDD principles. REST or GraphQL is just a kind of adapter. And the domain layer will be consistent all the time. So this repository implement GraphQL and REST at the same time.
The GraphQL schema is https://github.com/gothinkster/spring-boot-realworld-example-app/blob/master/src/main/resources/schema/schema.graphqls and the visualization looks like below.
And this implementation is using dgs-framework which is a quite new java graphql server framework.
How it works
The application uses Spring Boot (Web, Mybatis).
- Use the idea of Domain Driven Design to separate the business term and infrastructure term.
- Use MyBatis to implement the Data Mapper pattern for persistence.
- Use CQRS pattern to separate the read model and write model.
And the code is organized as this:
api
is the web layer implemented by Spring MVCcore
is the business model including entities and servicesapplication
is the high-level services for querying the data transfer objectsinfrastructure
contains all the implementation classes as the technique details
Security
Integration with Spring Security and add other filter for jwt token process.
The secret key is stored in application.properties
.
Database
It uses a H2 in-memory database sqlite database (for easy local test without losing test data after every restart), can be changed easily in the application.properties
for any other database.
Getting started
You'll need Java 11 installed.
./gradlew bootRun
To test that it works, open a browser tab at http://localhost:8080/tags .
Alternatively, you can run
curl http://localhost:8080/tags
Try it out with Docker
You'll need Docker installed.
./gradlew bootBuildImage --imageName spring-boot-realworld-example-app
docker run -p 8081:8080 spring-boot-realworld-example-app
Try it out with a RealWorld frontend
The entry point address of the backend API is at http://localhost:8080, not http://localhost:8080/api as some of the frontend documentation suggests.
Run test
The repository contains a lot of test cases to cover both api test and repository test.
./gradlew test
Code format
Use spotless for code format.
./gradlew spotlessJavaApply
Help
Please fork and PR to improve the project.
Top Related Projects
ASP.NET Core backend implementation for RealWorld
Exemplary real world backend API built with Laravel
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot