From 8e04a06bc916c1904c090a84e0918e3976f042bf Mon Sep 17 00:00:00 2001 From: lor6 Date: Sat, 4 Nov 2017 15:43:29 +0200 Subject: [PATCH] activiti with spring security example (#2909) --- spring-activiti/pom.xml | 9 +- .../java/com/baeldung/activiti/security.rar | Bin 0 -> 3760 bytes .../activiti/security/config/MvcConfig.java | 20 +++ .../security/config/ProcessController.java | 54 +++++++ .../config/SpringSecurityGroupManager.java | 86 +++++++++++ .../config/SpringSecurityUserManager.java | 144 ++++++++++++++++++ .../security/withactiviti/SecurityConfig.java | 47 ++++++ .../SpringSecurityActivitiApplication.java | 34 +++++ .../ActivitiSpringSecurityApplication.java | 39 +++++ .../security/withspring/SecurityConfig.java | 50 ++++++ spring-activiti/src/main/resources/data.sql | 3 + .../processes/protected-process.bpmn20.xml | 41 +++++ spring-activiti/src/main/resources/schema.sql | 3 + .../src/main/resources/templates/login.html | 21 +++ ...ActivitiSpringSecurityIntegrationTest.java | 31 ++++ 15 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security.rar create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java create mode 100644 spring-activiti/src/main/resources/data.sql create mode 100644 spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml create mode 100644 spring-activiti/src/main/resources/schema.sql create mode 100644 spring-activiti/src/main/resources/templates/login.html create mode 100644 spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java diff --git a/spring-activiti/pom.xml b/spring-activiti/pom.xml index c5289b20a6..f6f992b7c0 100644 --- a/spring-activiti/pom.xml +++ b/spring-activiti/pom.xml @@ -19,9 +19,11 @@ + com.example.activitiwithspring.ActivitiWithSpringApplication UTF-8 UTF-8 1.8 + 6.0.0 @@ -30,9 +32,14 @@ activiti-spring-boot-starter-basic 6.0.0 + + org.activiti + activiti-spring-boot-starter-security + ${activiti.version} + org.springframework.boot - spring-boot-starter-web + spring-boot-starter-thymeleaf diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security.rar b/spring-activiti/src/main/java/com/baeldung/activiti/security.rar new file mode 100644 index 0000000000000000000000000000000000000000..38c4946168a456265f5999633bc8cb581a8360cc GIT binary patch literal 3760 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 JUw{%B;9rQ$_E`V` literal 0 HcmV?d00001 diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java new file mode 100644 index 0000000000..f9394742cd --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.activiti.security.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/login") + .setViewName("login"); + registry.addViewController("/homepage") + .setViewName("homepage"); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java new file mode 100644 index 0000000000..671b246328 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java @@ -0,0 +1,54 @@ +package com.baeldung.activiti.security.config; + +import java.util.List; + +import org.activiti.engine.IdentityService; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.TaskService; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Task; +import org.activiti.spring.SpringProcessEngineConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ProcessController { + + @Autowired + private RuntimeService runtimeService; + + @Autowired + private TaskService taskService; + + @Autowired + private IdentityService identityService; + + @Autowired + SpringProcessEngineConfiguration config; + + @GetMapping("/protected-process") + public String startProcess() { + + String userId = SecurityContextHolder.getContext() + .getAuthentication() + .getName(); + + identityService.setAuthenticatedUserId(userId); + + ProcessInstance pi = runtimeService.startProcessInstanceByKey("protected-process"); + + List usertasks = taskService.createTaskQuery() + .processInstanceId(pi.getId()) + .list(); + + taskService.complete(usertasks.iterator() + .next() + .getId()); + + return "Process started. Number of currently running process instances = " + runtimeService.createProcessInstanceQuery() + .count(); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java new file mode 100644 index 0000000000..00fc674e22 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java @@ -0,0 +1,86 @@ +package com.baeldung.activiti.security.config; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.GroupQuery; +import org.activiti.engine.impl.GroupQueryImpl; +import org.activiti.engine.impl.Page; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityManagerImpl; +import org.activiti.engine.impl.persistence.entity.data.GroupDataManager; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +public class SpringSecurityGroupManager extends GroupEntityManagerImpl { + + private JdbcUserDetailsManager userManager; + + public SpringSecurityGroupManager(ProcessEngineConfigurationImpl processEngineConfiguration, GroupDataManager groupDataManager) { + super(processEngineConfiguration, groupDataManager); + } + + @Override + public List findGroupByQueryCriteria(GroupQueryImpl query, Page page) { + + if (query.getUserId() != null) { + return findGroupsByUser(query.getUserId()); + } + return null; + } + + @Override + public long findGroupCountByQueryCriteria(GroupQueryImpl query) { + return findGroupByQueryCriteria(query, null).size(); + } + + @Override + public List findGroupsByUser(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + System.out.println("group manager"); + if (userDetails != null) { + List groups = userDetails.getAuthorities() + .stream() + .map(a -> a.getAuthority()) + .map(a -> { + Group g = new GroupEntityImpl(); + g.setId(a); + return g; + }) + .collect(Collectors.toList()); + return groups; + } + return null; + } + + public void setUserManager(JdbcUserDetailsManager userManager) { + this.userManager = userManager; + } + + public Group createNewGroup(String groupId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + @Override + public void delete(String groupId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public GroupQuery createNewGroupQuery() { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public List findGroupsByNativeQuery(Map parameterMap, int firstResult, int maxResults) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public long findGroupCountByNativeQuery(Map parameterMap) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java new file mode 100644 index 0000000000..ce9863eb6c --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java @@ -0,0 +1,144 @@ +package com.baeldung.activiti.security.config; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.User; +import org.activiti.engine.identity.UserQuery; +import org.activiti.engine.impl.Page; +import org.activiti.engine.impl.UserQueryImpl; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityImpl; +import org.activiti.engine.impl.persistence.entity.UserEntity; +import org.activiti.engine.impl.persistence.entity.UserEntityImpl; +import org.activiti.engine.impl.persistence.entity.UserEntityManagerImpl; +import org.activiti.engine.impl.persistence.entity.data.UserDataManager; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +public class SpringSecurityUserManager extends UserEntityManagerImpl { + + private JdbcUserDetailsManager userManager; + + public SpringSecurityUserManager(ProcessEngineConfigurationImpl processEngineConfiguration, UserDataManager userDataManager, JdbcUserDetailsManager userManager) { + super(processEngineConfiguration, userDataManager); + this.userManager = userManager; + } + + @Override + public UserEntity findById(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + if (userDetails != null) { + UserEntityImpl user = new UserEntityImpl(); + user.setId(userId); + return user; + } + return null; + + } + + @Override + public List findUserByQueryCriteria(UserQueryImpl query, Page page) { + List users = null; + if (query.getGroupId() != null) { + users = userManager.findUsersInGroup(query.getGroupId()) + .stream() + .map(username -> { + User user = new UserEntityImpl(); + user.setId(username); + return user; + }) + .collect(Collectors.toList()); + if (page != null) { + return users.subList(page.getFirstResult(), page.getFirstResult() + page.getMaxResults()); + + } + return users; + } + + if (query.getId() != null) { + UserDetails userDetails = userManager.loadUserByUsername(query.getId()); + if (userDetails != null) { + UserEntityImpl user = new UserEntityImpl(); + user.setId(query.getId()); + return Collections.singletonList(user); + } + } + return null; + } + + @Override + public Boolean checkPassword(String userId, String password) { + return true; + } + + public void setUserManager(JdbcUserDetailsManager userManager) { + this.userManager = userManager; + } + + public User createNewUser(String userId) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public void updateUser(User updatedUser) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public void delete(UserEntity userEntity) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + @Override + public void deletePicture(User user) { + UserEntity userEntity = (UserEntity) user; + if (userEntity.getPictureByteArrayRef() != null) { + userEntity.getPictureByteArrayRef() + .delete(); + } + } + + public void delete(String userId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public long findUserCountByQueryCriteria(UserQueryImpl query) { + return findUserByQueryCriteria(query, null).size(); + } + + public List findGroupsByUser(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + if (userDetails != null) { + List groups = userDetails.getAuthorities() + .stream() + .map(a -> a.getAuthority()) + .map(a -> { + Group g = new GroupEntityImpl(); + g.setId(a); + return g; + }) + .collect(Collectors.toList()); + return groups; + } + return null; + } + + public UserQuery createNewUserQuery() { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public List findUsersByNativeQuery(Map parameterMap, int firstResult, int maxResults) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public long findUserCountByNativeQuery(Map parameterMap) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java new file mode 100644 index 0000000000..f471600553 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java @@ -0,0 +1,47 @@ +package com.baeldung.activiti.security.withactiviti; + +import org.activiti.engine.IdentityService; +import org.activiti.spring.security.IdentityServiceUserDetailsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +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.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/**") + .authorizeRequests() + .antMatchers("/protected-process*") + .authenticated() + .anyRequest() + .permitAll() + .and() + .formLogin() + .loginPage("/login") + .defaultSuccessUrl("/homepage") + .failureUrl("/login?error=true") + .and() + .csrf() + .disable() + .logout() + .logoutSuccessUrl("/login"); + } + + @Autowired + private IdentityService identityService; + + @Bean + public IdentityServiceUserDetailsService userDetailsService() { + return new IdentityServiceUserDetailsService(identityService); + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService()); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java new file mode 100644 index 0000000000..2270a4d684 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java @@ -0,0 +1,34 @@ +package com.baeldung.activiti.security.withactiviti; + +import org.activiti.engine.IdentityService; +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.User; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication(scanBasePackages = { "com.baeldung.activiti.security.config", "com.baeldung.activiti.security.withactiviti" }) +public class SpringSecurityActivitiApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityActivitiApplication.class, args); + } + + @Bean + InitializingBean usersAndGroupsInitializer(IdentityService identityService) { + return new InitializingBean() { + public void afterPropertiesSet() throws Exception { + User user = identityService.newUser("activiti_user"); + user.setPassword("pass"); + identityService.saveUser(user); + + Group group = identityService.newGroup("user"); + group.setName("ROLE_USER"); + group.setType("USER"); + identityService.saveGroup(group); + identityService.createMembership(user.getId(), group.getId()); + } + }; + } +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java new file mode 100644 index 0000000000..5878a5d678 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java @@ -0,0 +1,39 @@ +package com.baeldung.activiti.security.withspring; + +import org.activiti.engine.impl.persistence.entity.data.impl.MybatisGroupDataManager; +import org.activiti.engine.impl.persistence.entity.data.impl.MybatisUserDataManager; +import org.activiti.spring.SpringProcessEngineConfiguration; +import org.activiti.spring.boot.SecurityAutoConfiguration; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +import com.baeldung.activiti.security.config.SpringSecurityGroupManager; +import com.baeldung.activiti.security.config.SpringSecurityUserManager; + +@SpringBootApplication(exclude = SecurityAutoConfiguration.class, scanBasePackages = { "com.baeldung.activiti.security.config", "com.baeldung.activiti.security.withspring" }) +public class ActivitiSpringSecurityApplication { + + public static void main(String[] args) { + SpringApplication.run(ActivitiSpringSecurityApplication.class, args); + } + + @Autowired + private SpringProcessEngineConfiguration processEngineConfiguration; + + @Autowired + private JdbcUserDetailsManager userManager; + + @Bean + InitializingBean processEngineInitializer() { + return new InitializingBean() { + public void afterPropertiesSet() throws Exception { + processEngineConfiguration.setUserEntityManager(new SpringSecurityUserManager(processEngineConfiguration, new MybatisUserDataManager(processEngineConfiguration), userManager)); + processEngineConfiguration.setGroupEntityManager(new SpringSecurityGroupManager(processEngineConfiguration, new MybatisGroupDataManager(processEngineConfiguration))); + } + }; + } +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java new file mode 100644 index 0000000000..df1991c3e4 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java @@ -0,0 +1,50 @@ +package com.baeldung.activiti.security.withspring; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +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.WebSecurityConfigurerAdapter; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/**") + .authorizeRequests() + .antMatchers("/protected-process*") + .authenticated() + .anyRequest() + .permitAll() + .and() + .formLogin() + .loginPage("/login") + .defaultSuccessUrl("/homepage") + .failureUrl("/login?error=true") + .and() + .csrf() + .disable() + .logout() + .logoutSuccessUrl("/login"); + } + + @Bean + public JdbcUserDetailsManager userDetailsManager() { + JdbcUserDetailsManager manager = new JdbcUserDetailsManager(); + manager.setDataSource(dataSource); + return manager; + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsManager()); + } + +} diff --git a/spring-activiti/src/main/resources/data.sql b/spring-activiti/src/main/resources/data.sql new file mode 100644 index 0000000000..cb9b72617a --- /dev/null +++ b/spring-activiti/src/main/resources/data.sql @@ -0,0 +1,3 @@ +insert into users(username, password, enabled) values ('spring_user', 'pass', true); + +insert into authorities(username, authority) values ('spring_user','ROLE_USER'); \ No newline at end of file diff --git a/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml b/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml new file mode 100644 index 0000000000..b7e04515cd --- /dev/null +++ b/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + ROLE_USER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-activiti/src/main/resources/schema.sql b/spring-activiti/src/main/resources/schema.sql new file mode 100644 index 0000000000..bf882895fd --- /dev/null +++ b/spring-activiti/src/main/resources/schema.sql @@ -0,0 +1,3 @@ +create table users(username varchar(255), password varchar(255), enabled boolean); + +create table authorities(username varchar(255),authority varchar(255)); \ No newline at end of file diff --git a/spring-activiti/src/main/resources/templates/login.html b/spring-activiti/src/main/resources/templates/login.html new file mode 100644 index 0000000000..53077fd5f3 --- /dev/null +++ b/spring-activiti/src/main/resources/templates/login.html @@ -0,0 +1,21 @@ + + + +

Login

+
+ + + + + + + + + + + + +
User:
Password:
+
+ + \ No newline at end of file diff --git a/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java b/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java new file mode 100644 index 0000000000..c2eeb96555 --- /dev/null +++ b/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java @@ -0,0 +1,31 @@ +package com.example.activitiwithspring; + +import org.activiti.engine.IdentityService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.activiti.security.withspring.ActivitiSpringSecurityApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ActivitiSpringSecurityApplication.class) +@WebAppConfiguration +public class ActivitiSpringSecurityIntegrationTest { + @Autowired + private IdentityService identityService; + + @Test + public void whenUserExists_thenOk() { + identityService.setUserPicture("spring_user", null); + } + + @Test(expected = UsernameNotFoundException.class) + public void whenUserNonExistent_thenSpringException() { + identityService.setUserPicture("user3", null); + } + +}