Merge branch 'eugenp:master' into danielmcnally285_string_to_long

This commit is contained in:
danielmcnally285 2023-12-30 22:14:14 +00:00 committed by GitHub
commit 3dbd82fe17
78 changed files with 1593 additions and 314 deletions

View File

@ -8,4 +8,5 @@ The code examples related to different libraries are each in their own module.
Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-modules) we already have separate modules. Please make sure to have a look at the existing modules in such cases.
### Relevant articles
- [Find Files by Extension in Specified Directory in Java](https://www.baeldung.com/java-recursive-search-directory-extension-match)
- More articles [[<-- prev]](/libraries-6)

View File

@ -9,9 +9,9 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
<relativePath>../parent-boot-3</relativePath>
</parent>
<dependencies>
@ -20,9 +20,8 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${spring-security-oauth2.version}</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@ -68,6 +67,29 @@
<artifactId>jsch</artifactId>
<version>${jsch.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
@ -125,7 +147,6 @@
<bouncycastle.version>1.68</bouncycastle.version>
<jsch.version>0.1.55</jsch.version>
<apache-mina.version>2.5.1</apache-mina.version>
<spring-security-oauth2.version>2.4.0.RELEASE</spring-security-oauth2.version>
<xacml4j.version>1.4.0</xacml4j.version>
</properties>

View File

@ -4,7 +4,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class ScribejavaApplication {
@ -13,5 +12,4 @@ public class ScribejavaApplication {
SpringApplication.run(ScribejavaApplication.class, args);
}
}

View File

@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
@RestController
public class GoogleController {

View File

@ -2,15 +2,14 @@ package com.baeldung.scribejava.controller;
import java.io.IOException;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.annotation.security.DeclareRoles;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.HttpConstraint;
import jakarta.servlet.annotation.ServletSecurity;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet(name="rbac", urlPatterns = {"/protected"})
@DeclareRoles("USER")

View File

@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;

View File

@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import java.security.Principal;
@RestController(value = "/user")

View File

@ -1,45 +1,103 @@
package com.baeldung.scribejava.oauth;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
@Configuration
@EnableAuthorizationServer
public class AuthServiceConfig extends AuthorizationServerConfigurerAdapter {
@EnableWebSecurity
public class AuthServiceConfig {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
@Bean
public SecurityFilterChain securityFilter(HttpSecurity http) throws Exception {
http.headers( it -> it.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("baeldung_api_key")
.secret("baeldung_api_secret")
.authorizedGrantTypes("password","refresh_token")
.scopes("read","write").autoApprove(true);
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withUsername("baeldung")
.password("scribejava")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("baeldung_api_key")
.clientSecret("baeldung_api_secret")
.authorizationGrantType(AuthorizationGrantType.PASSWORD)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.scope("read")
.scope("write")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(false).build())
.build();
return new InMemoryRegisteredClientRepository(oidcClient);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
http
// Redirect to the login page when not authenticated from the
// authorization endpoint
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
)
// Accept access tokens for User Info and/or Client Registration
.oauth2ResourceServer((resourceServer) -> resourceServer
.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
// Form login handles the redirect to the login page from the
// authorization server filter chain
.formLogin(Customizer.withDefaults());
return http.build();
}
}

View File

@ -1,53 +0,0 @@
package com.baeldung.scribejava.oauth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
@Configuration
@EnableResourceServer
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("baeldung")
.password("scribejava")
.roles("USER");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@EnableResourceServer
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/me").authenticated()
.and()
.csrf().disable();
}
}
}

View File

@ -5,7 +5,7 @@ import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.OAuth20Service;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
@Component
public class GoogleService {

View File

@ -5,7 +5,7 @@ import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.OAuth20Service;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
@Component
public class MyService {

View File

@ -5,7 +5,7 @@ import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.OAuth10aService;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
@Component
public class TwitterService {

View File

@ -1,5 +1,6 @@
package com.baeldung.hibernate;
import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
@ -74,5 +75,13 @@ public class CustomClassIntegrationTest {
assertEquals("Sales", result.getDepartmentName());
}
@Test
public void whenCastResultQueryToList_ThenListOfResultIsReturned() {
Query<Result> query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name) "
+ "from DeptEmployee m");
List<Result> results = query.list();
assertNotNull(results);
assertEquals(1, results.size());
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.spring.data.persistence.findvsget;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApplicationConfig {
}

View File

@ -0,0 +1,90 @@
package com.baeldung.spring.data.persistence.findvsget.entity;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "users")
public class User {
@Id
@Column(name = "id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "second_name")
private String secondName;
public User() {
}
public User(final Long id, final String firstName, final String secondName) {
this.id = id;
this.firstName = firstName;
this.secondName = secondName;
}
public void setId(final Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(final String secondName) {
this.secondName = secondName;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final User user = (User) o;
if (!Objects.equals(id, user.id)) {
return false;
}
if (!Objects.equals(firstName, user.firstName)) {
return false;
}
return Objects.equals(secondName, user.secondName);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (secondName != null ? secondName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", secondName='" + secondName + '\'' +
'}';
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.spring.data.persistence.findvsget.repository;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository
public interface NewTransactionUserRepository extends JpaRepository<User, Long> {
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
User getReferenceById(Long id);
@Override
Optional<User> findById(Long id);
}

View File

@ -0,0 +1,10 @@
package com.baeldung.spring.data.persistence.findvsget.repository;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SimpleUserRepository extends JpaRepository<User, Long> {
}

View File

@ -0,0 +1,33 @@
package com.baeldung.spring.data.persistence.findvsget.service;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class NonTransactionalUserReferenceService {
private static final Logger log = LoggerFactory.getLogger(NonTransactionalUserReferenceService.class);
private SimpleUserRepository repository;
public User findUserReference(final long id) {
log.info("Before requesting a user");
final User user = repository.getReferenceById(id);
log.info("After requesting a user");
return user;
}
public User findAndUseUserReference(final long id) {
final User user = repository.getReferenceById(id);
log.info("Before accessing a username");
final String firstName = user.getFirstName();
log.info("This message shouldn't be displayed because of the thrown exception: {}", firstName);
return user;
}
public void setRepository(final SimpleUserRepository repository) {
this.repository = repository;
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.spring.data.persistence.findvsget.service;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class SimpleUserService {
private static final Logger log = LoggerFactory.getLogger(SimpleUserService.class);
private final SimpleUserRepository repository;
public SimpleUserService(final SimpleUserRepository repository) {
this.repository = repository;
}
public User findUser(final long id) {
log.info("Before requesting a user in a findUser method");
final Optional<User> optionalUser = repository.findById(id);
log.info("After requesting a user in a findUser method");
final User user = optionalUser.orElse(null);
log.info("After unwrapping an optional in a findUser method");
return user;
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.spring.data.persistence.findvsget.service;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TransactionalUserReferenceService {
private static final Logger log = LoggerFactory.getLogger(TransactionalUserReferenceService.class);
private JpaRepository<User, Long> repository;
@Transactional
public User findUserReference(final long id) {
log.info("Before requesting a user");
final User user = repository.getReferenceById(id);
log.info("After requesting a user");
return user;
}
@Transactional
public User findAndUseUserReference(final long id) {
final User user = repository.getReferenceById(id);
log.info("Before accessing a username");
final String firstName = user.getFirstName();
log.info("After accessing a username: {}", firstName);
return user;
}
public void setRepository(final JpaRepository<User, Long> repository) {
this.repository = repository;
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.spring.data.persistence.findvsget;
import static com.baeldung.spring.data.persistence.findvsget.UserProvider.userSource;
import static org.assertj.core.api.Assumptions.assumeThat;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.provider.Arguments;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = ApplicationConfig.class, properties = {
"spring.jpa.generate-ddl=true",
"spring.jpa.show-sql=false"
})
abstract class DatabaseConfigurationBaseIntegrationTest {
private static final int NUMBER_OF_USERS = 10;
@Autowired
private SimpleUserRepository repository;
@BeforeEach
void populateDatabase() {
final List<User> users = userSource()
.map(Arguments::get)
.map(s -> new User(((Long) s[0]), s[1].toString(), s[2].toString()))
.collect(Collectors.toList());
repository.saveAll(users);
assumeThat(repository.findAll()).hasSize(NUMBER_OF_USERS);
}
@AfterEach
void clearDatabase() {
repository.deleteAll();
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.spring.data.persistence.findvsget;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import com.baeldung.spring.data.persistence.findvsget.service.SimpleUserService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
@DisplayName("findBy test:")
class FindUserIntegrationIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
@Autowired
private SimpleUserService service;
@ParameterizedTest
@ArgumentsSource(UserProvider.class)
@DisplayName("when looking for a user by an existing ID returns a user")
void whenGettingUserByCorrectIdThenReturnUser(Long id, String firstName, String lastName) {
final User expected = new User(id, firstName, lastName);
final User actual = service.findUser(id);
assertThat(actual).isEqualTo(expected);
}
@ParameterizedTest
@DisplayName("when looking for a user by a non-existing ID returns null")
@ValueSource(longs = {11, 12, 13})
void whenGettingUserByIncorrectIdThenReturnNull(Long id) {
assertThat(service.findUser(id)).isNull();
}
}

View File

@ -0,0 +1,125 @@
package com.baeldung.spring.data.persistence.findvsget;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import com.baeldung.spring.data.persistence.findvsget.entity.User;
import com.baeldung.spring.data.persistence.findvsget.repository.NewTransactionUserRepository;
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
import com.baeldung.spring.data.persistence.findvsget.service.NonTransactionalUserReferenceService;
import com.baeldung.spring.data.persistence.findvsget.service.TransactionalUserReferenceService;
import org.hibernate.LazyInitializationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
@DisplayName("getReferenceBy test:")
class GetReferenceIntegrationIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
private static final long EXISTING_ID = 1L;
@Nested
@DisplayName("given non-transactional service, even if user exists")
class GivenNonTransactionalService {
@Autowired
private NonTransactionalUserReferenceService nonTransactionalService;
@BeforeEach
void configureService(@Autowired SimpleUserRepository repository) {
nonTransactionalService.setRepository(repository);
}
@Test
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
final User user = nonTransactionalService.findUserReference(EXISTING_ID);
assertThatExceptionOfType(LazyInitializationException.class)
.isThrownBy(user::getFirstName);
}
@Test
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
final User user = nonTransactionalService.findUserReference(EXISTING_ID);
assertThat(user).isNotNull();
}
@Test
void whenFindUserReferenceUsingInsideServiceThenThrowsException() {
assertThatExceptionOfType(LazyInitializationException.class)
.isThrownBy(() -> nonTransactionalService.findAndUseUserReference(EXISTING_ID));
}
}
@Nested
@DisplayName("given transactional service with simple repository, even if user exists")
class GivenTransactionalService {
@Autowired
private TransactionalUserReferenceService transactionalService;
@BeforeEach
void configureService(@Autowired SimpleUserRepository repository) {
transactionalService.setRepository(repository);
}
@Test
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
final User user = transactionalService.findUserReference(EXISTING_ID);
assertThatExceptionOfType(LazyInitializationException.class)
.isThrownBy(user::getFirstName);
}
@Test
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
final User user = transactionalService.findUserReference(EXISTING_ID);
assertThat(user).isNotNull();
}
@ParameterizedTest
@ArgumentsSource(UserProvider.class)
void whenFindUserReferenceUsingInsideServiceThenReturnsUser(Long id, String firstName, String lastName) {
final User expected = new User(id, firstName, lastName);
final User actual = transactionalService.findAndUseUserReference(id);
assertThat(actual).isEqualTo(expected);
}
}
@Nested
@DisplayName("given transactional service with new transaction repository, even if user exists")
class GivenTransactionalServiceWithNewTransactionRepository {
@Autowired
private TransactionalUserReferenceService transactionalServiceWithNewTransactionRepository;
@BeforeEach
void configureService(@Autowired NewTransactionUserRepository repository) {
transactionalServiceWithNewTransactionRepository.setRepository(repository);
}
@Test
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
final User user = transactionalServiceWithNewTransactionRepository
.findUserReference(EXISTING_ID);
assertThatExceptionOfType(LazyInitializationException.class)
.isThrownBy(user::getFirstName);
}
@Test
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
final User user = transactionalServiceWithNewTransactionRepository.findUserReference(EXISTING_ID);
assertThat(user).isNotNull();
}
@Test
void whenFindUserReferenceUsingInsideServiceThenThrowsExceptionDueToSeparateTransactions() {
assertThatExceptionOfType(LazyInitializationException.class)
.isThrownBy(() -> transactionalServiceWithNewTransactionRepository
.findAndUseUserReference(EXISTING_ID));
}
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.spring.data.persistence.findvsget;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
public class UserProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(final ExtensionContext context) {
return userSource();
}
static Stream<Arguments> userSource() {
return Stream.of(
Arguments.of(1L, "Saundra", "Krystek"),
Arguments.of(2L, "Korey", "Venners"),
Arguments.of(3L, "Lory", "Daffey"),
Arguments.of(4L, "Michail", "Spinella"),
Arguments.of(5L, "Emanuel", "Geertje"),
Arguments.of(6L, "Jervis", "Waugh"),
Arguments.of(7L, "Chantal", "Soldan"),
Arguments.of(8L, "Darnall", "Fanner"),
Arguments.of(9L, "Cordelia", "Hindge"),
Arguments.of(10L, "Lem", "Pitcock")
);
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.caseinsensitiveenum.converter;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import org.springframework.core.convert.converter.Converter;
public class CaseInsensitiveWeekDayConverter implements Converter<String, WeekDays> {
@Override
public WeekDays convert(final String source) {
try {
return WeekDays.valueOf(source.trim());
} catch (IllegalArgumentException exception) {
return WeekDays.valueOf(source.trim().toUpperCase());
}
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.caseinsensitiveenum.converter;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import org.springframework.core.convert.converter.Converter;
public class StrictNullableWeekDayConverter implements Converter<String, WeekDays> {
@Override
public WeekDays convert(final String source) {
try {
return WeekDays.valueOf(source.trim());
} catch (IllegalArgumentException e) {
return null;
}
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.caseinsensitiveenum.nonconventionalweek;
public enum NonConventionalWeekDays {
Mon$Day, Tues$DAY_, Wednes$day, THURS$day_, Fri$Day$_$, Satur$DAY_, Sun$Day
}

View File

@ -0,0 +1,85 @@
package com.baeldung.caseinsensitiveenum.nonconventionalweek;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class NonConventionalWeekDaysHolder {
@Value("${monday}")
private NonConventionalWeekDays monday;
@Value("${tuesday}")
private NonConventionalWeekDays tuesday;
@Value("${wednesday}")
private NonConventionalWeekDays wednesday;
@Value("${thursday}")
private NonConventionalWeekDays thursday;
@Value("${friday}")
private NonConventionalWeekDays friday;
@Value("${saturday}")
private NonConventionalWeekDays saturday;
@Value("${sunday}")
private NonConventionalWeekDays sunday;
public NonConventionalWeekDays getMonday() {
return monday;
}
public void setMonday(final NonConventionalWeekDays monday) {
this.monday = monday;
}
public NonConventionalWeekDays getTuesday() {
return tuesday;
}
public void setTuesday(final NonConventionalWeekDays tuesday) {
this.tuesday = tuesday;
}
public NonConventionalWeekDays getWednesday() {
return wednesday;
}
public void setWednesday(final NonConventionalWeekDays wednesday) {
this.wednesday = wednesday;
}
public NonConventionalWeekDays getThursday() {
return thursday;
}
public void setThursday(final NonConventionalWeekDays thursday) {
this.thursday = thursday;
}
public NonConventionalWeekDays getFriday() {
return friday;
}
public void setFriday(final NonConventionalWeekDays friday) {
this.friday = friday;
}
public NonConventionalWeekDays getSaturday() {
return saturday;
}
public void setSaturday(final NonConventionalWeekDays saturday) {
this.saturday = saturday;
}
public NonConventionalWeekDays getSunday() {
return sunday;
}
public void setSunday(final NonConventionalWeekDays sunday) {
this.sunday = sunday;
}
}

View File

@ -0,0 +1,85 @@
package com.baeldung.caseinsensitiveenum.week;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SpELWeekDaysHolder {
@Value("#{'${monday}'.toUpperCase()}")
private WeekDays monday;
@Value("#{'${tuesday}'.toUpperCase()}")
private WeekDays tuesday;
@Value("#{'${wednesday}'.toUpperCase()}")
private WeekDays wednesday;
@Value("#{'${thursday}'.toUpperCase()}")
private WeekDays thursday;
@Value("#{'${friday}'.toUpperCase()}")
private WeekDays friday;
@Value("#{'${saturday}'.toUpperCase()}")
private WeekDays saturday;
@Value("#{'${sunday}'.toUpperCase()}")
private WeekDays sunday;
public WeekDays getMonday() {
return monday;
}
public void setMonday(final WeekDays monday) {
this.monday = monday;
}
public WeekDays getTuesday() {
return tuesday;
}
public void setTuesday(final WeekDays tuesday) {
this.tuesday = tuesday;
}
public WeekDays getWednesday() {
return wednesday;
}
public void setWednesday(final WeekDays wednesday) {
this.wednesday = wednesday;
}
public WeekDays getThursday() {
return thursday;
}
public void setThursday(final WeekDays thursday) {
this.thursday = thursday;
}
public WeekDays getFriday() {
return friday;
}
public void setFriday(final WeekDays friday) {
this.friday = friday;
}
public WeekDays getSaturday() {
return saturday;
}
public void setSaturday(final WeekDays saturday) {
this.saturday = saturday;
}
public WeekDays getSunday() {
return sunday;
}
public void setSunday(final WeekDays sunday) {
this.sunday = sunday;
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.caseinsensitiveenum.week;
public enum WeekDays {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

View File

@ -0,0 +1,85 @@
package com.baeldung.caseinsensitiveenum.week;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class WeekDaysHolder {
@Value("${monday}")
private WeekDays monday;
@Value("${tuesday}")
private WeekDays tuesday;
@Value("${wednesday}")
private WeekDays wednesday;
@Value("${thursday}")
private WeekDays thursday;
@Value("${friday}")
private WeekDays friday;
@Value("${saturday}")
private WeekDays saturday;
@Value("${sunday}")
private WeekDays sunday;
public WeekDays getMonday() {
return monday;
}
public void setMonday(final WeekDays monday) {
this.monday = monday;
}
public WeekDays getTuesday() {
return tuesday;
}
public void setTuesday(final WeekDays tuesday) {
this.tuesday = tuesday;
}
public WeekDays getWednesday() {
return wednesday;
}
public void setWednesday(final WeekDays wednesday) {
this.wednesday = wednesday;
}
public WeekDays getThursday() {
return thursday;
}
public void setThursday(final WeekDays thursday) {
this.thursday = thursday;
}
public WeekDays getFriday() {
return friday;
}
public void setFriday(final WeekDays friday) {
this.friday = friday;
}
public WeekDays getSaturday() {
return saturday;
}
public void setSaturday(final WeekDays saturday) {
this.saturday = saturday;
}
public WeekDays getSunday() {
return sunday;
}
public void setSunday(final WeekDays sunday) {
this.sunday = sunday;
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.CaseInsensitiveStringToEnumConverterUnitTest.WeekDayConverterConfiguration;
import com.baeldung.caseinsensitiveenum.converter.CaseInsensitiveWeekDayConverter;
import com.baeldung.caseinsensitiveenum.providers.WeekDayHolderArgumentsProvider;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.WeekDaysHolder;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
@SpringBootTest(properties = {
"monday=monday",
"tuesday=tuesday",
"wednesday=wednesday",
"thursday=THURSDAY",
"friday=Friday",
"saturday=saturDAY",
"sunday=sUndAy",
}, classes = {WeekDaysHolder.class, WeekDayConverterConfiguration.class})
class CaseInsensitiveStringToEnumConverterUnitTest {
public static class WeekDayConverterConfiguration {
@Bean
public ConversionService conversionService() {
final DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new CaseInsensitiveWeekDayConverter());
return defaultConversionService;
}
}
@Autowired
private WeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(WeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsNull(
Function<WeekDaysHolder, WeekDays> methodReference, WeekDays expected) {
WeekDays actual = methodReference.apply(holder);
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.providers.WeekDayHolderArgumentsProvider;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.WeekDaysHolder;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = {
"monday=Mon-Day!",
"tuesday=TuesDAY#",
"wednesday=Wednes@day",
"thursday=THURSday^",
"friday=Fri:Day_%",
"saturday=Satur_DAY*",
"sunday=Sun+Day",
}, classes = WeekDaysHolder.class)
class LenientStringToEnumConverterUnitTest {
@Autowired
private WeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(WeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsPresent(
Function<WeekDaysHolder, WeekDays> methodReference, WeekDays expected) {
WeekDays actual = methodReference.apply(holder);
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays;
import com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDaysHolder;
import com.baeldung.caseinsensitiveenum.providers.NonConventionalWeekDayHolderArgumentsProvider;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = {
"monday=Mon-Day!",
"tuesday=TuesDAY#",
"wednesday=Wednes@day",
"thursday=THURSday^",
"friday=Fri:Day_%",
"saturday=Satur_DAY*",
"sunday=Sun+Day",
}, classes = NonConventionalWeekDaysHolder.class)
class NonConventionalStringToEnumLenientConverterUnitTest {
@Autowired
private NonConventionalWeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(NonConventionalWeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsPresent(
Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays> methodReference, NonConventionalWeekDays expected) {
NonConventionalWeekDays actual = methodReference.apply(holder);
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.CaseInsensitiveStringToEnumConverterUnitTest.WeekDayConverterConfiguration;
import com.baeldung.caseinsensitiveenum.converter.StrictNullableWeekDayConverter;
import com.baeldung.caseinsensitiveenum.providers.SpELWeekDayHolderArgumentsProvider;
import com.baeldung.caseinsensitiveenum.week.SpELWeekDaysHolder;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
@SpringBootTest(properties = {
"monday=monday",
"tuesday=tuesday",
"wednesday=wednesday",
"thursday=THURSDAY",
"friday=Friday",
"saturday=saturDAY",
"sunday=sUndAy",
}, classes = {SpELWeekDaysHolder.class, WeekDayConverterConfiguration.class})
class SpELCaseInsensitiveStringToEnumConverterUnitTest {
public static class WeekDayConverterConfiguration {
@Bean
public ConversionService conversionService() {
final DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new StrictNullableWeekDayConverter());
return defaultConversionService;
}
}
@Autowired
private SpELWeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(SpELWeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsNull(
Function<SpELWeekDaysHolder, WeekDays> methodReference, WeekDays expected) {
WeekDays actual = methodReference.apply(holder);
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.StrictStringToEnumConverterNegativeUnitTest.WeekDayConverterConfiguration;
import com.baeldung.caseinsensitiveenum.converter.StrictNullableWeekDayConverter;
import com.baeldung.caseinsensitiveenum.providers.WeekDayHolderArgumentsProvider;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.WeekDaysHolder;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
@SpringBootTest(properties = {
"monday=monday",
"tuesday=tuesday",
"wednesday=wednesday",
"thursday=thursday",
"friday=friday",
"saturday=saturday",
"sunday=sunday",
}, classes = {WeekDaysHolder.class, WeekDayConverterConfiguration.class})
class StrictStringToEnumConverterNegativeUnitTest {
public static class WeekDayConverterConfiguration {
@Bean
public ConversionService conversionService() {
final DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new StrictNullableWeekDayConverter());
return defaultConversionService;
}
}
@Autowired
private WeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(WeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsNull(
Function<WeekDaysHolder, WeekDays> methodReference, WeekDays ignored) {
WeekDays actual = methodReference.apply(holder);
assertThat(actual).isNull();
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.caseinsensitiveenum;
import static org.assertj.core.api.Assertions.assertThat;
import com.baeldung.caseinsensitiveenum.StrictStringToEnumConverterNegativeUnitTest.WeekDayConverterConfiguration;
import com.baeldung.caseinsensitiveenum.converter.StrictNullableWeekDayConverter;
import com.baeldung.caseinsensitiveenum.providers.WeekDayHolderArgumentsProvider;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.WeekDaysHolder;
import java.util.function.Function;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
@SpringBootTest(properties = {
"monday=MONDAY",
"tuesday=TUESDAY",
"wednesday=WEDNESDAY",
"thursday=THURSDAY",
"friday=FRIDAY",
"saturday=SATURDAY",
"sunday=SUNDAY",
}, classes = {WeekDaysHolder.class, WeekDayConverterConfiguration.class})
class StrictStringToEnumConverterPositiveUnitTest {
public static class WeekDayConverterConfiguration {
@Bean
public ConversionService conversionService() {
final DefaultConversionService defaultConversionService = new DefaultConversionService();
defaultConversionService.addConverter(new StrictNullableWeekDayConverter());
return defaultConversionService;
}
}
@Autowired
private WeekDaysHolder holder;
@ParameterizedTest
@ArgumentsSource(WeekDayHolderArgumentsProvider.class)
void givenPropertiesWhenInjectEnumThenValueIsNull(
Function<WeekDaysHolder, WeekDays> methodReference, WeekDays expected) {
WeekDays actual = methodReference.apply(holder);
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.caseinsensitiveenum.providers;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Fri$Day$_$;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Mon$Day;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Satur$DAY_;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Sun$Day;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.THURS$day_;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Tues$DAY_;
import static com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays.Wednes$day;
import com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDays;
import com.baeldung.caseinsensitiveenum.nonconventionalweek.NonConventionalWeekDaysHolder;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
public class NonConventionalWeekDayHolderArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(final ExtensionContext extensionContext) {
return Stream.of(
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getMonday),Mon$Day),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getTuesday),Tues$DAY_),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getWednesday),Wednes$day),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getThursday),THURS$day_),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getFriday),Fri$Day$_$),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getSaturday),Satur$DAY_),
Arguments.of(((Function<NonConventionalWeekDaysHolder, NonConventionalWeekDays>) NonConventionalWeekDaysHolder::getSunday),Sun$Day)
);
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.caseinsensitiveenum.providers;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.FRIDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.MONDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.SATURDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.SUNDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.THURSDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.TUESDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.WEDNESDAY;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.SpELWeekDaysHolder;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
public class SpELWeekDayHolderArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(final ExtensionContext extensionContext) {
return Stream.of(
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getMonday), MONDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getTuesday), TUESDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getWednesday), WEDNESDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getThursday), THURSDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getFriday), FRIDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getSaturday), SATURDAY),
Arguments.of(((Function<SpELWeekDaysHolder, WeekDays>) SpELWeekDaysHolder::getSunday), SUNDAY)
);
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.caseinsensitiveenum.providers;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.FRIDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.MONDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.SATURDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.SUNDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.THURSDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.TUESDAY;
import static com.baeldung.caseinsensitiveenum.week.WeekDays.WEDNESDAY;
import com.baeldung.caseinsensitiveenum.week.WeekDays;
import com.baeldung.caseinsensitiveenum.week.WeekDaysHolder;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
public class WeekDayHolderArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(final ExtensionContext extensionContext) {
return Stream.of(
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getMonday), MONDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getTuesday), TUESDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getWednesday), WEDNESDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getThursday), THURSDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getFriday), FRIDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getSaturday), SATURDAY),
Arguments.of(((Function<WeekDaysHolder, WeekDays>) WeekDaysHolder::getSunday), SUNDAY)
);
}
}

View File

@ -1,3 +1,6 @@
## Spring Reactive Performance
This module contains articles about reactive Spring Boot.
## Relevant Articles
- [Reactor WebFlux vs Virtual Threads](https://www.baeldung.com/java-reactor-webflux-vs-virtual-threads)

View File

@ -11,8 +11,9 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>spring-security-modules</artifactId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent>
<dependencies>
@ -34,7 +35,7 @@
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -81,11 +82,6 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
@ -100,6 +96,11 @@
<version>${ehcache-core.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -15,14 +15,14 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
@PropertySource({"classpath:persistence-h2.properties", "classpath:application-defaults.properties"})
@EnableJpaRepositories(basePackages = {"com.baeldung.relationships.repositories"})
@EnableWebMvc
@Import(SpringSecurityConfig.class)
public class AppConfig extends WebMvcConfigurerAdapter {
public class AppConfig implements WebMvcConfigurer {
@Autowired
private Environment env;
@ -41,7 +41,7 @@ public class AppConfig extends WebMvcConfigurerAdapter {
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.baeldung.relationships.models" });
em.setPackagesToScan("com.baeldung.relationships.models");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(additionalProperties());
return em;

View File

@ -1,6 +1,6 @@
package com.baeldung.relationships;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +13,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
@ -47,12 +48,10 @@ public class SpringSecurityConfig {
@Bean
public UserDetailsManager users(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.passwordEncoder(encoder())
.and()
.authenticationProvider(authenticationProvider())
.build();
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(encoder());
authenticationManagerBuilder.authenticationProvider(authenticationProvider());
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);
jdbcUserDetailsManager.setAuthenticationManager(authenticationManager);
@ -61,22 +60,16 @@ public class SpringSecurityConfig {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring()
.antMatchers("/resources/**");
return web -> web.ignoring().requestMatchers("/resources/**");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login")
.permitAll()
.and()
.formLogin()
.permitAll()
.successHandler(successHandler)
.and()
.csrf()
.disable();
http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry.requestMatchers("/login").permitAll())
.formLogin(httpSecurityFormLoginConfigurer ->
httpSecurityFormLoginConfigurer.permitAll().successHandler(successHandler))
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}

View File

@ -2,12 +2,12 @@ package com.baeldung.relationships.models;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")

View File

@ -3,14 +3,14 @@ package com.baeldung.relationships.models;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "Tweet")

View File

@ -3,11 +3,12 @@ package com.baeldung.relationships.repositories;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.baeldung.relationships.models.Tweet;
public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {
public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long>, CrudRepository<Tweet, Long> {
@Query("SELECT twt FROM Tweet twt JOIN twt.likes AS lk WHERE lk = ?#{ principal?.username } OR twt.owner = ?#{ principal?.username }")
Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable);

View File

@ -2,8 +2,8 @@ package com.baeldung.relationships.security;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;

View File

@ -1,6 +1,6 @@
package com.baeldung.relationships.security;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;

View File

@ -2,8 +2,11 @@ package com.baeldung.roles.custom.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@ -14,14 +17,9 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.anyRequest().authenticated())
.formLogin(AbstractAuthenticationFilterConfigurer::permitAll);
return http.build();
}

View File

@ -3,7 +3,7 @@ package com.baeldung.roles.custom.persistence;
import java.util.Arrays;
import java.util.HashSet;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import com.baeldung.roles.custom.persistence.dao.OrganizationRepository;
import com.baeldung.roles.custom.persistence.dao.PrivilegeRepository;

View File

@ -1,10 +1,10 @@
package com.baeldung.roles.custom.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Foo {

View File

@ -1,10 +1,10 @@
package com.baeldung.roles.custom.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Organization {

View File

@ -1,10 +1,10 @@
package com.baeldung.roles.custom.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Privilege {

View File

@ -2,17 +2,17 @@ package com.baeldung.roles.custom.persistence.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name = "user_table")
@ -28,7 +28,9 @@ public class User {
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "users_privileges", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id"))
@JoinTable(name = "users_privileges", joinColumns =
@JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id"))
private Set<Privilege> privileges;
@ManyToOne(fetch = FetchType.EAGER)

View File

@ -6,10 +6,13 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
@Configuration
@EnableWebSecurity
@ -32,19 +35,12 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login")
.permitAll()
.antMatchers("/foos/**")
.access("isAuthenticated() and hasIpAddress('11.11.11.11')")
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.and()
.csrf()
.disable();
http.authorizeHttpRequests(
authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry.requestMatchers("/login").permitAll()
.requestMatchers("/foos/**")
.access(new WebExpressionAuthorizationManager("isAuthenticated() and hasIpAddress('11.11.11.11')")).anyRequest().authenticated())
.formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}

View File

@ -2,8 +2,8 @@ package com.baeldung.roles.ip.web;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import com.baeldung.roles.custom.persistence.model.Foo;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -2,9 +2,9 @@ package com.baeldung.roles.rolesauthorities;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

View File

@ -10,6 +10,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@ -42,33 +43,22 @@ public class SecurityConfig {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring()
.antMatchers("/resources/**");
return (web) -> web.ignoring().requestMatchers("/resources/**");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login*", "/logout*", "/protectedbynothing*", "/home*")
.permitAll()
.antMatchers("/protectedbyrole")
.hasRole("USER")
.antMatchers("/protectedbyauthority")
.hasAuthority("READ_PRIVILEGE")
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.permitAll()
.and()
.logout()
.logoutSuccessHandler(myLogoutSuccessHandler)
.invalidateHttpSession(false)
.logoutSuccessUrl("/logout.html?logSucc=true")
.deleteCookies("JSESSIONID")
.permitAll();
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(
authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry.requestMatchers("/login*", "/logout*", "/protectedbynothing*", "/home*").permitAll()
.requestMatchers("/protectedbyrole").hasRole("USER")
.requestMatchers("/protectedbyauthority").hasAuthority("READ_PRIVILEGE"))
.formLogin(httpSecurityFormLoginConfigurer ->
httpSecurityFormLoginConfigurer.loginPage("/login").failureUrl("/login?error=true").permitAll())
.logout(httpSecurityLogoutConfigurer ->
httpSecurityLogoutConfigurer.logoutSuccessHandler(myLogoutSuccessHandler).invalidateHttpSession(false)
.logoutSuccessUrl("/logout.html?logSucc=true").deleteCookies("JSESSIONID").permitAll());
return http.build();
}

View File

@ -2,11 +2,11 @@ package com.baeldung.roles.rolesauthorities.model;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
@Entity
public class Privilege {

View File

@ -2,13 +2,13 @@ package com.baeldung.roles.rolesauthorities.model;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
@Entity
public class Role {

View File

@ -2,17 +2,16 @@ package com.baeldung.roles.rolesauthorities.model;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "user_account")

View File

@ -1,6 +1,6 @@
package com.baeldung.roles.rolesauthorities.persistence;
import javax.transaction.Transactional;
import jakarta.transaction.Transactional;
import com.baeldung.roles.rolesauthorities.model.User;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -1,33 +1,28 @@
package com.baeldung.roles.voter;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.function.Supplier;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
public class MinuteBasedVoter implements AccessDecisionVoter {
public class MinuteBasedVoter implements AuthorizationManager<RequestAuthorizationContext> {
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
public void verify(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
AuthorizationManager.super.verify(authentication, object);
}
@Override
public boolean supports(Class clazz) {
return true;
}
@Override
public int vote(Authentication authentication, Object object, Collection collection) {
return authentication.getAuthorities()
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
return authentication.get().getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.filter(r -> "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0)
.findAny()
.map(s -> ACCESS_DENIED)
.orElse(ACCESS_ABSTAIN);
.findAny().map(s -> new AuthorizationDecision(false))
.orElse(new AuthorizationDecision(true));
}
}

View File

@ -1,23 +1,19 @@
package com.baeldung.roles.voter;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.access.vote.UnanimousBased;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationManagers;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
@Configuration
@EnableWebSecurity
@ -38,32 +34,20 @@ public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.accessDecisionManager(accessDecisionManager())
.and()
.formLogin()
.permitAll()
.and()
.logout()
.permitAll()
.deleteCookies("JSESSIONID")
.logoutSuccessUrl("/login");
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry.anyRequest().authenticated()
.anyRequest().access(accessDecisionManager()))
.formLogin(AbstractAuthenticationFilterConfigurer::permitAll)
.logout(httpSecurityLogoutConfigurer ->
httpSecurityLogoutConfigurer.permitAll().deleteCookies("JSESSIONID")
.logoutSuccessUrl("/login"));
return http.build();
}
@Bean
public AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<?>> decisionVoters = Arrays.asList(
new WebExpressionVoter(),
new RoleVoter(),
new AuthenticatedVoter(),
new MinuteBasedVoter());
return new UnanimousBased(decisionVoters);
public AuthorizationManager<RequestAuthorizationContext> accessDecisionManager() {
return AuthorizationManagers.allOf(new MinuteBasedVoter());
}
@Bean

View File

@ -11,9 +11,9 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -25,7 +25,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import javax.servlet.ServletContext;
import jakarta.servlet.ServletContext;
import java.util.Date;
import java.util.List;
@ -83,7 +83,7 @@ public class SpringDataWithSecurityIntegrationTest {
userRepository.updateLastLogin(new Date());
}
@Test(expected = InvalidDataAccessApiUsageException.class)
@Test(expected = SpelEvaluationException.class)
public void givenNoAppUserInSecurityContext_whenUpdateLastLoginAttempted_shouldFail() {
userRepository.updateLastLogin(new Date());
}
@ -104,7 +104,7 @@ public class SpringDataWithSecurityIntegrationTest {
} while (page.hasNext());
}
@Test(expected = InvalidDataAccessApiUsageException.class)
@Test(expected = SpelEvaluationException.class)
public void givenNoAppUser_whenPaginatedResultsRetrievalAttempted_shouldFail() {
Page<Tweet> page = null;
do {

View File

@ -6,13 +6,13 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.apache.http.HttpHeaders;
import com.baeldung.roles.custom.Application;
import com.baeldung.roles.custom.persistence.model.Foo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithUserDetails;

View File

@ -15,6 +15,12 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<spock-core.version>2.4-M1-groovy-4.0</spock-core.version>
<groovy-all.version>4.0.16</groovy-all.version>
<gmavenplus-plugin.version>3.0.2</gmavenplus-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.spockframework</groupId>
@ -23,9 +29,10 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy-all.version}</version>
<type>pom</type>
</dependency>
</dependencies>
@ -39,18 +46,34 @@
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
<configuration>
<testSources>
<testSource>
<directory>${project.basedir}/src/test/groovy</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<testSourceDirectory>src/test/groovy</testSourceDirectory>
<includes>
<include>**/*Specification.groovy</include>
<include>**/*Test.groovy</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<spock-core.version>1.3-groovy-2.4</spock-core.version>
<groovy-all.version>2.4.7</groovy-all.version>
<gmavenplus-plugin.version>1.5</gmavenplus-plugin.version>
</properties>
</project>

View File

@ -0,0 +1,11 @@
package mocks;
public class Book {
private String title;
private String author;
Book(String title, String author) {
this.title = title;
this.author = author;
}
}

View File

@ -0,0 +1,5 @@
package mocks;
public interface BookRepository {
Book findById(Long id);
}

View File

@ -0,0 +1,13 @@
package mocks;
public class BookService {
private final BookRepository repository;
public BookService(BookRepository repository) {
this.repository = repository;
}
public Book getBookDetails(Long id) {
return repository.findById(id);
}
}

View File

@ -0,0 +1,7 @@
package mocks;
public class MessageService {
public String fetchMessage() {
return UtilityClass.getMessage();
}
}

View File

@ -0,0 +1,26 @@
package mocks;
import java.util.HashMap;
import java.util.Map;
public class ShoppingCart {
private final Map<String, Integer> items = new HashMap<>();
private double totalPrice = 0.0;
public void addItem(String item, int quantity) {
items.put(item, items.getOrDefault(item, 0) + quantity);
totalPrice += quantity * 2.00; // Example pricing
}
public int getTotalItems() {
return items.values().stream().mapToInt(Integer::intValue).sum();
}
public double getTotalPrice() {
return totalPrice;
}
public boolean containsItem(String item) {
return items.containsKey(item);
}
}

View File

@ -0,0 +1,7 @@
package mocks;
public class UtilityClass {
public static String getMessage() {
return "Original Message";
}
}

View File

@ -0,0 +1,21 @@
package extensions
import mocks.ShoppingCart
import spock.lang.Specification
class ShoppingCartTest extends Specification {
def "verify multiple properties of a ShoppingCart"() {
given:
ShoppingCart cart = new ShoppingCart()
cart.addItem("Apple", 3)
cart.addItem("Banana", 2)
expect:
with(cart) {
totalItems == 5
totalPrice == 10.00
items.contains("Apple")
items.contains("Banana")
}
}
}

View File

@ -0,0 +1,25 @@
package mocks
import spock.lang.Specification
class BookServiceTest extends Specification {
def "should retrieve book details and verify method calls"() {
given:
def bookRepository = Mock(BookRepository) {
findById(1L) >> new Book("Effective Java", "Joshua Bloch")
findById(2L) >> null
}
def bookService = new BookService(bookRepository)
when:
Book effectiveJava = bookService.getBookDetails(1L)
Book unknownBook = bookService.getBookDetails(2L)
then:
1 * bookRepository.findById(1L)
1 * bookRepository.findById(2L)
effectiveJava.title == "Effective Java"
unknownBook == null
}
}

View File

@ -0,0 +1,20 @@
package mocks
import spock.lang.Specification
class MessageServiceTest extends Specification {
def "should use global mock for UtilityClass"() {
given:
def utilityMock = GroovySpy(UtilityClass, global: true)
utilityMock.getMessage() >> "Mocked Message"
when:
MessageService service = new MessageService()
String message = service.fetchMessage()
then:
1 * utilityMock.getMessage()
message == "Mocked Message"
}
}

View File

@ -4,3 +4,5 @@ This module contains articles about (Timefold Solver)[https://timefold.ai].
### Relevant articles
- [A Guide to Timefold Solver for Employee Scheduling](https://www.baeldung.com/java-timefold-solver-guide)