Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Save and Delete Bidirectional Foreign key entities

 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I am using a User, Role and UserRole class with bidirectional relationship. I am not able to save or delete userrole object in database. Here are the classes

User.java


Role.java

UserRole.java


I am using angularjs (front end) to communicate with spring-data-jpa(backend) to perform save and delete operations. I tried saving the id's of user and role directly into db but it throws an exception
ERROR: org.springframework.data.rest.webmvc.AbstractRepositoryRestController - not-null property references a null or transient value : com.ellora.collorado.model.UserRole.employee; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : com.ellora.collorado.model.UserRole.employee
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value : com.ellora.collorado.model.UserRole.employee; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : com.ellora.collorado.model.UserRole.employee
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:207)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy82.save(Unknown Source)
at org.springframework.data.rest.core.invoke.CrudRepositoryInvoker.invokeSave(CrudRepositoryInvoker.java:106)
at org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:414)
at org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(RepositoryEntityController.java:232)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:799)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:728)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)


So I fetched both the objects using the id's and then tried to store them, there was no exception but the values weren't stored in database. Same is the case for delete. Kindly help me.

Regards
Parthe
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Probably a similar issue as in your other bidirectional issue.

When you have a bidirectional association, it's your responsibility to make the changes at both sides to ensure that your object model is consistent. So you can't delete an object by only its id.
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

For delete, its ok but I am struggling with add for about a week now . Today I tried something similar in add like what you instructed me for delete but I am not able to bring the object from angularjs to Spring data jpa. Usually what we do is pass the id in url but I think we won't be able to pass an object in url. Help me out here please
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you explain why class Role has a UserRole collection? That makes no sense at all. But that's probably because you have a bidirectional relationship. Having bidirectional relationships complicate your model (and code) as you already experienced the past week. So I would only use them when it has some added value. Don't use bidirectional relationships by default as it will probably result in more complex code without any added value.

Here you'll find some examples of many-to-many relationships. Look especially to the Advanced section, it is very similar to your use case (ProjectAssociation = UserRole)
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

As I told you earlier this code was given to me by my seniors, I am new here. Say If I remove Set<UserRole> from Role class it would become Unidirectional and what about Employee then? Will I have to remove bidirectional there too? In case that solves the problem, I am ready to give it a try.

I tried as per the example provided is the advanced section as you have mentioned but I am not able to take it further. Two things are interrupting

1) If I comment out my Id field in UserRole(ProjectAssociation in the example), I am not able to run the project as the id field is associated with several other modules.

2) Even if I some how manage to run the project, I have only the ID's. I can call the Role(Project).addEmployee(Employee employee) method by passing the id's to a function in java controller and then call it. I don't think that is preferred. Correct me if I am wrong.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Partheban Udayakumar wrote:As I told you earlier this code was given to me by my seniors,

So I assume you could ask your seniors for advice. They probably use a model they are familiar with and already have experience with saving/deleting data using a similar model.

Partheban Udayakumar wrote:2) Even if I some how manage to run the project, I have only the ID's. I can call the Role(Project).addEmployee(Employee employee) method by passing the id's to a function in java controller and then call it. I don't think that is preferred. Correct me if I am wrong.

Using a bidirectional relationship, it's your responsibility to make the changes at both sides to ensure that your object model is consistent. That's really important.

So I would expect you'll have some method likeAnd then in Employee and Role you have a addUserRole method like

Hope it helps!
Kind regards,
Roel
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

I tried your example but I think there is some mistake in what I do with angularjs part. I have implemented the solution in UserRoleServiceImplementation and have called it from UserRoleController using angularjs but it says POST method not supported and the userrole doesn't add. Here is what I tried for calling UserRoleController from angular js

controller.js


services.js



UserRoleController.java



Here is the output it shows

WARN : org.springframework.web.servlet.PageNotFound - Request method 'POST' not supported
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A nice overview of all involved code but the most important part is missing: the actual url to which the POST request is sent...
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

Actual url?? I don't get it. From the controller.js "UserRole.saveUserRole()", it goes to services.js "saveUserRole: {method: 'POST', url: appConfig.apiRootPath + 'userRoles/:userId/:roleId/add'}" and then this calls UserRoleController's "@RequestMapping(value = "/{userId}/{roleId}/add", method = POST)". This is the flow, I have been taught. If you want the full url that is called, its "localhost:8080/#/api/userRoles/25/2/add"

I forgot to mention that UserRoleController has this,



and btw UserRole delete works fine, thanks for that too.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Partheban Udayakumar wrote:If you want the full url that is called, its "localhost:8080/#/api/userRoles/25/2/add"

That was indeed what I was looking for If that url is wrong, you can do whatever changes you want to your backend but it won't work. But the url looks ok! And your request-mapping should match with that url.

But the saveUserRole method in UserRole (services.js) defines userRole (not userRoles) in the url. But in your last post, it defines userRoles. So I assume you have already made some changes.

With the current code, I would think the addUserRole method in UserRoleController will be executed if you perform a POST-request to url "localhost:8080/#/api/userRoles/25/2/add". Did you already try setting the debug level of your application to DEBUG? Then you get more info about the different controllers (and paths) Spring MVC tries to match your url against.

And maybe you could use Postman (from Chrome Web Store) for debugging purposes. I use it myself as well to quickly execute some test requests (get, post,...) with or without payload, with or without headers. It's a very powerful tool.
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

Ya. I have added the 's' as you have mentioned but I am not able to add still. I don't know about setting my app to DEBUG level, could you please brief me about it?? I will definitely try postman

EDIT 1: I tried Postman, it gives me only the 405 report. I am not able to figure out any thing from that.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Partheban Udayakumar wrote:EDIT 1: I tried Postman, it gives me only the 405 report. I am not able to figure out any thing from that.

405 = method not allowed

So you have an url which accepts e.g. a POST request and you are sending a GET request instead...
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Partheban Udayakumar wrote:I don't know about setting my app to DEBUG level, could you please brief me about it??

It all depends on which logging framework you are using...
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:
405 = method not allowed

So you have an url which accepts e.g. a POST request and you are sending a GET request instead...


This is clear from the eclipse console warning which I had provided. I have method = POST in UserRoleController and in service, I use method: 'POST' but I don't know how it mismatches??

Roel De Nijs wrote:
It all depends on which logging framework you are using...


I don't even know the basics of debugging, could you please provide me a link where I can start about debugging?? As for logging framework, I am using the Log4j (1.6.6)
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If your request doesn't enter the method defined in your controller, it's very hard to debug. That's why setting the log level to DEBUG only for spring mvc classes will give you some info about the url to request mapping matching process.

As you are using log4j, you'll have a log4j.properties file somewhere. So just addor you could just set the rootLogger level to DEBUG. Here and here (if you have log4 xml config file) you'll find more info. And I'm pretty sure your seniors will be happy to learn you how to change the logging level of your application to retrieve valuable information.
 
Partheban Udayakumar
Ranch Hand
Posts: 496
AngularJS Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel,

I tried debugging as you said but nothing appears in my eclipse console when I call UserRole.save() function. What does this mean? No request is sent using the model? If so how can I solve this?
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Partheban Udayakumar wrote:I tried debugging as you said but nothing appears in my eclipse console when I call UserRole.save() function. What does this mean? No request is sent using the model? If so how can I solve this?

The main question still is: you have a method in your UserRoleController to add a user role. If you add a user role in the front-end, does your program enter the appropriate method of the UserRoleController class?
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic