How can I combine two spring -data-mongdb collections as ManyToMany (RDBMS)

I have an example from https://github.com/szerhusenBC/jwt-spring-security-demo/ which I am trying to use mongodb as my backend, but I am getting an error due to the code in JwtUserFactory.java

 return authorities.stream() .map(authority -> new SimpleGrantedAuthority(authority.getName().name())) .collect(Collectors.toList()); 

Because of the Authority and User class in the model.security package that uses RDBMS connections, but I use mongodb and get an error in my code. I have Authority and User defined for Mongodb as shown below. Can anyone guide me to get a job

Authority.java

 @Document(collection = "authority") public class Authority { @Id private Long id; private AuthorityName name; @DBRef(lazy = true) private List<User> users; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public AuthorityName getName() { return name; } public void setName(AuthorityName name) { this.name = name; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } } 

User.java

 @Document(collection = "user") public class User { @Id private Long _id; private String username; private String password; private String firstname; private String lastname; private String email; private Boolean enabled; private Date lastPasswordResetDate; @DBRef(lazy = true) private List<Authority> authorities; public Long getId() { return _id; } public void setId(Long id) { _id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Boolean getEnabled() { return enabled; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } public List<Authority> getAuthorities() { return authorities; } public void setAuthorities(List<Authority> authorities) { this.authorities = authorities; } public Date getLastPasswordResetDate() { return lastPasswordResetDate; } public void setLastPasswordResetDate(Date lastPasswordResetDate) { this.lastPasswordResetDate = lastPasswordResetDate; } } 

UserRepository.java

 public interface UserRepository extends MongoRepository<User, Double> { User findByUsername(String username); } 

Exception

Below is the exception that I am getting

  org.springframework.security.authentication.InternalAuthenticationServiceException: null at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.parkcity.security.controller.AuthenticationRestController.createAuthenticationToken(AuthenticationRestController.java:44) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) ~[tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.parkcity.security.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:58) [classes/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410) [tomcat-embed-core-8.5.6.jar:8.5.6] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.6.jar:8.5.6] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.6.jar:8.5.6] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111] Caused by: java.lang.NullPointerException: null at org.parkcity.security.JwtUserFactory.mapToGrantedAuthorities(JwtUserFactory.java:31) ~[classes/:na] at org.parkcity.security.JwtUserFactory.create(JwtUserFactory.java:24) ~[classes/:na] at org.parkcity.security.service.JwtUserDetailsServiceImpl.loadUserByUsername(JwtUserDetailsServiceImpl.java:25) ~[classes/:na] at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:114) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE] ... 93 common frames omitted 2017-01-13 00:04:11.543 DEBUG 30067 --- [nio-8080-exec-1] osswaExceptionTranslationFilter : Calling Authentication entry point. 2017-01-13 00:04:11.544 DEBUG 30067 --- [nio-8080-exec-1] osswheader.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.se curity.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@ 12337118 2017-01-13 00:04:11.544 DEBUG 30067 --- [nio-8080-exec-1] sswcSecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 
+5
source share
2 answers

Basically you have more than one problem with your code. First of all, the project you are referencing is created based on JPA (this is a relational database), and if you want to use the same code base with Mongo DB (document storage), at least you need to rethink the data model (User and Power). But first, let's try to make this example work, and in the end I would just advise that this could also change.

First of all, if you use MongoDb for the best experience, the domain fields of the id domain must be of type String, since you know that mongodb stores identifiers as ObjectId bson type, which cannot be converted to Long. So first change User.java to

 @Document(collection = "user") public class User { @Id private String _id; // bla bla bla } 

Same thing with the Permissions object

 @Document(collection = "authority") public class Authority { @Id private String _id; // TODO remove this right now !!! :) @DBRef(lazy = true) private List<User> users; // bla bla bla } 

And UserRepository

 public interface UserRepository extends MongoRepository<User, String> { User findByUsername(String username); } 

After these two changes, you will also need to reorganize the links.

Do you have a link from authorities to users? !!! What is this? :) This is something from JPA, with MongoDb this link does not make sense. Just delete it!

The next thing related to the project is that it relies on the fact that the data store has some predefined data, see import.sql , so for MongoDb you need to import the data into mongodb in order to be able to run the project. I converted import.sql to MongoShell format so you can use it.

Paste this into the authority collection:

 { "_id" : ObjectId("587cb19d1db2732183afb0a9"), "_class" : "org.parkcity.model.security.Authority", "name" : "ROLE_ADMIN" } { "_id" : ObjectId("587cb19d1db2732183afb0aa"), "_class" : "org.parkcity.model.security.Authority", "name" : "ROLE_USER" } 

Paste this into the user collection:

 { "_id" : ObjectId("587cb19d1db2732183afb0ab"), "_class" : "org.parkcity.model.security.User", "username" : "admin", "password" : "$2a$08$lDnHPz7eUkSi6ao14Twuau08mzhWrL4kyZGGU5xfiGALO/Vxd5DOi", "firstname" : "admin", "lastname" : "admin", "email" : " admin@admin.com ", "enabled" : true, "lastPasswordResetDate" : ISODate("2017-01-16T11:42:21.537+0000"), "authorities" : [ DBRef("authority", ObjectId("587cb19d1db2732183afb0a9")), DBRef("authority", ObjectId("587cb19d1db2732183afb0aa")) ] } { "_id" : ObjectId("587cb1a11db2732183afb0ac"), "_class" : "org.parkcity.model.security.User", "username" : "user", "password" : "$2a$08$UkVvwpULis18S19S5pZFn.YHPZt3oaqHZnDwqbCW9pft6uFtkXKDC", "firstname" : "user", "lastname" : "user", "email" : " user@user.com ", "enabled" : true, "lastPasswordResetDate" : ISODate("2017-01-16T11:42:21.620+0000"), "authorities" : [ DBRef("authority", ObjectId("587cb19d1db2732183afb0aa")) ] } 

As you can see, I adjusted the packages from "org.zerhusen" to "org.parkcity".

Here it is, now you can start the project and conduct some tests. As you can see, I did not add a disconnected user (so you can do it yourself).

And just for your reasons, for this particular case using @DBRefs is a pure evil :) You are on MogoDb, so keep credentials in the same collection and object as the users, so it will be much faster.

A fully functional fork (based on MongoDB) has also been created, which is available here https://github.com/babltiga/jwt-spring-security-demo p>

+5
source

Mongodb, a document-based repository, requires a different modeling experience than you are used to in SQL.

In the above case, since Authority is such a tiny object, I would just include

 List<String> authorities 

in User. Then you have one collection without any crack, which is associated with the need to maintain referential integrity, and also improves performance.

The disadvantage is that when changing permissions, namely when renaming or deleting, you need to update all user documents, but judging by your data model, this will happen infrequently.

+1
source

Source: https://habr.com/ru/post/1262495/


All Articles