juneau-shaded-rest-server-springboot
The juneau-shaded-rest-server-springboot artifact bundles REST server functionality plus Spring Boot integration. At 3.8 MB, it provides everything needed for building Juneau REST services with Spring Boot.
What's Included
This artifact includes:
- All modules from juneau-shaded-rest-server (core + REST server)
- juneau-rest-server-springboot - Spring Boot auto-configuration and integration
Use Cases
Use juneau-shaded-rest-server-springboot when you need:
- Spring Boot applications - Leverage Spring Boot's ecosystem
- Auto-configuration - Automatic Juneau setup with Spring Boot
- Spring dependency injection - Use
@Autowiredin REST resources - Spring Security integration - Leverage Spring's security framework
- Spring ecosystem - Access to Spring Data, Spring Cloud, etc.
Maven Dependency
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-rest-server-springboot</artifactId>
<version>${juneau.version}</version>
</dependency>
Bazel Dependency
maven_jar(
name = "juneau_rest_server_springboot",
artifact = "org.apache.juneau:juneau-shaded-rest-server-springboot:${juneau.version}",
)
# External dependencies
maven_jar(
name = "spring_boot_starter_web",
artifact = "org.springframework.boot:spring-boot-starter-web:3.2.0",
)
java_library(
name = "my_spring_api",
srcs = glob(["src/**/*.java"]),
deps = [
"@juneau_rest_server_springboot//jar",
"@spring_boot_starter_web//jar",
],
)
External Dependencies
juneau-shaded-rest-server-springboot requires:
Required
- Spring Boot Starter Web 3.0+ - Spring Boot web support
- Jakarta Servlet API 6.1+ - Servlet specification (transitively from Spring Boot)
Optional
- Spring Boot Starter Security - For Spring Security integration
- Jakarta XML Bind API 3.0+ - For XML serialization
- Apache Jena - For RDF support
Example Usage
Spring Boot Application
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
REST Resource with Spring Integration
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.springboot.*;
import org.springframework.beans.factory.annotation.Autowired;
@Rest(
path="/api/pets",
title="Pet Store API"
)
public class PetResource extends SpringRestServlet {
@Autowired
private PetService petService; // Spring bean injection
@RestGet
public List<Pet> getAllPets() {
return petService.findAll();
}
@RestGet(path="/{id}")
public Pet getPet(@Path long id) {
return petService.findById(id)
.orElseThrow(() -> new NotFound("Pet not found"));
}
@RestPost
public Pet createPet(@Content Pet pet) {
return petService.save(pet);
}
}
Spring Configuration
import org.springframework.context.annotation.Configuration;
import org.apache.juneau.rest.springboot.JuneauRestInitializer;
@Configuration
public class JuneauConfig implements JuneauRestInitializer {
@Override
public void init(SpringRestServletBuilder builder) {
builder
.defaultAccept("application/json")
.defaultContentType("application/json")
.maxInput("10M");
}
}
Application Properties
# application.properties
# Juneau settings
juneau.defaultAccept=application/json
juneau.defaultContentType=application/json
juneau.maxInput=10M
# Server settings
server.port=8080
server.servlet.context-path=/
# Logging
logging.level.org.apache.juneau=DEBUG
Spring Security Integration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
}
Accessing Security Context
@Rest(path="/api/users")
public class UserResource extends SpringRestServlet {
@RestGet(path="/me")
public User getCurrentUser() {
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
String username = auth.getName();
return userService.findByUsername(username);
}
}
Spring Data Integration
import org.springframework.data.jpa.repository.JpaRepository;
public interface PetRepository extends JpaRepository<Pet, Long> {
List<Pet> findBySpecies(String species);
}
@Rest(path="/api/pets")
public class PetResource extends SpringRestServlet {
@Autowired
private PetRepository petRepository;
@RestGet
public List<Pet> getAllPets(
@Query("species") String species
) {
if (species != null)
return petRepository.findBySpecies(species);
return petRepository.findAll();
}
}
Transaction Management
import org.springframework.transaction.annotation.Transactional;
@Rest(path="/api/orders")
public class OrderResource extends SpringRestServlet {
@Autowired
private OrderService orderService;
@RestPost
@Transactional
public Order createOrder(@Content Order order) {
// Transactional operation
return orderService.create(order);
}
}
Exception Handling with Spring
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(
EntityNotFoundException ex
) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse(ex.getMessage()));
}
}
Swagger Integration
@Rest(
path="/api",
swagger=@Swagger(
title="Pet Store API",
version="1.0",
description="REST API for Pet Store",
contact=@Contact(
name="Support Team",
email="support@example.com"
),
license=@License(
name="Apache 2.0",
url="http://www.apache.org/licenses/LICENSE-2.0.html"
)
)
)
public class PetStoreApi extends SpringRestServlet {
// Swagger UI at: http://localhost:8080/api/swagger
// OpenAPI JSON at: http://localhost:8080/api/openapi.json
}
Multi-Module Spring Boot Application
// Main application
@SpringBootApplication
@ComponentScan(basePackages = {
"com.example.api",
"com.example.service"
})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
// REST resources in com.example.api
@Rest(path="/users")
@Component
public class UserResource extends SpringRestServlet {
@Autowired
private UserService userService;
// ...
}
// Services in com.example.service
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// ...
}
Features
Spring Boot Auto-Configuration
- Automatic servlet registration
- Property-based configuration
- Actuator integration
- Metrics and health checks
Spring Ecosystem Integration
- Spring Data - Database access
- Spring Security - Authentication/authorization
- Spring Cloud - Microservices patterns
- Spring Cache - Caching abstraction
- Spring Scheduling - Task scheduling
Juneau Features
All features from juneau-shaded-rest-server plus:
- Spring bean injection in REST resources
- Access to Spring ApplicationContext
- Integration with Spring's exception handling
- Spring's AOP capabilities
Testing
Spring Boot Test
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ExtendWith(SpringExtension.class)
public class PetResourceTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testGetAllPets() {
ResponseEntity<Pet[]> response = restTemplate
.getForEntity("/api/pets", Pet[].class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response.getBody().length > 0);
}
}
MockMvc Integration
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(PetResource.class)
public class PetResourceMockMvcTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private PetService petService;
@Test
public void testGetPet() throws Exception {
Pet pet = new Pet(1L, "Fluffy", "cat");
when(petService.findById(1L))
.thenReturn(Optional.of(pet));
mockMvc.perform(get("/api/pets/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Fluffy"));
}
}
Migration from Individual Modules
Before:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-server</artifactId>
<version>${juneau.version}</version>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-server-springboot</artifactId>
<version>${juneau.version}</version>
</dependency>
After:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-rest-server-springboot</artifactId>
<version>${juneau.version}</version>
</dependency>
Next Steps
- Need client functionality too? Use juneau-shaded-all
- Learn about REST server: See REST Server Basics
- Learn about Spring Boot integration: See Spring Boot Integration
- Learn about Spring Security: See Spring Security Integration
Share feedback or follow-up questions for this page directly through GitHub.