1 Reply Latest reply on Jan 13, 2010 1:27 PM by lvdberg

    Problem using Seam identity management with User -> Role link table

    lanroth

      Hi there,


      I'm trying to record information about the relationship between a user and a role.  Specifically the period of time that the user is or was in a role.  Later I want to record which user created the relationship.


      To store this information I created a UserAccountRole entity which links the UserAccount and UserRole entities.


      I've replaced the existing @ManyToMany relationship between UserAccount and UserRole with @ManyToOne relationships in UserAccountRole.


      Here's the code I've got so far:
      Note: I've removed all simple unannotated getters/setters for brievity.


      @Entity
      @Table(name="USER_ACCOUNT")
      public class UserAccount implements Serializable {
          private long id;
          private String username;
          private String password;
          private String fullName;
          private Set<UserAccountRole> userAccountRoles=new HashSet<UserAccountRole>();
      
          @Id @GeneratedValue
          public long getId() { return id; }
      
          @UserPrincipal
          public String getUsername() { return username; }
      
          @UserPassword(hash = "none")
          public String getPassword() { return password; }
      
          @UserRoles
          @OneToMany(mappedBy="userAccount")
          @Column(name="USER_ACCOUNT_ROLE")
          public Set<UserAccountRole> getUserAccountRoles() { return userAccountRoles; }
      }
      
      @Entity
      @Table(name="USER_ROLE")
      public class UserRole implements Serializable {
          private Long id;
          private String name;
          private String description;
          private Set<UserRole> groups;
      
          @RoleGroups
          @ManyToMany
          @JoinTable(
                  name = "user_role_group",
                  joinColumns = @JoinColumn(name = "id"),
                  inverseJoinColumns = @JoinColumn(name = "member_of_role"))
      
          public Set<UserRole> getGroups() { return groups; }
      
          @Id @GeneratedValue
          public Long getId() { return id; }
      
          @RoleName
          @Length(max = 20)
          public String getName() {return name;}
      }
      
      @Entity
      @Table(name="USER_ACCOUNT_ROLE")
      public class UserAccountRole implements Serializable{
          private Long id;
          private Date startDate;
          private Date endDate;
          private UserAccount userAccount;
          private UserRole userRole;
      
          @Id @GeneratedValue
          public Long getId() {return id;}
      
          @ManyToOne
          public UserAccount getUserAccount() {return userAccount;}
      
          @ManyToOne
          public UserRole getUserRole() {
              return userRole;
          }
      }



      My components.xml has:


      <security:jpa-identity-store
        user-class="org.example.entity.user.UserAccount"
        role-class="org.example.entity.user.UserRole"/>




      When I try to login I get [SeamLoginModule] Error invoking login method in the log.


      When I debug into the login I determined that the exception being thrown is:
      java.lang.IllegalArgumentException: Could not invoke method by reflection: UserRole.getName() on: org.example.entity.user.UserAccountRole


      It looks to me that UserRole.getName() is being called on an object of type UserAccountRole which is clearly wrong but I'm not sure what to do from here.  Any ideas?



      And the stack at this point looks like:


      Daemon Thread [http-0.0.0.0-8080-1] (Suspended (breakpoint at line 150 in Reflections))
          Reflections.invokeAndWrap(Method, Object, Object...) line: 150
          AnnotatedBeanProperty<T>.getValue(Object) line: 115
          JpaIdentityStore.getImpliedRoles(String) line: 719
          IdentityManager.getImpliedRoles(String) line: 254
          SeamLoginModule.login() line: 130
          NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
          NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
          DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
          Method.invoke(Object, Object...) line: 597
          LoginContext.invoke(String) line: 769
          LoginContext.access$000(LoginContext, String) line: 186
          LoginContext$5.run() line: 706
          AccessController.doPrivileged(PrivilegedExceptionAction<T>, AccessControlContext) line: not available [native method]
          LoginContext.invokeCreatorPriv(String) line: 703
          LoginContext.login() line: 575
          Identity.authenticate(LoginContext) line: 344
          Identity.authenticate() line: 332
          Identity.login() line: 259
          NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
          NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
          DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
          Method.invoke(Object, Object...) line: 597
          ReflectionUtil.invokeMethod(Object, Method, Object[]) line: 335
          ReflectionUtil.invokeMethod(Object, Object, Class[], Object[]) line: 348
          AstPropertySuffix.invoke(Object, EvaluationContext, Class[], Object[]) line: 58
          AstValue.invoke(EvaluationContext, Class[], Object[]) line: 96
          MethodExpressionImpl.invoke(ELContext, Object[]) line: 276
          TagMethodExpression.invoke(ELContext, Object[]) line: 68
          MethodBindingMethodExpressionAdapter.invoke(FacesContext, Object[]) line: 88
          ActionListenerImpl.processAction(ActionEvent) line: 102
          HtmlCommandButton(UICommand).broadcast(FacesEvent) line: 387
          AjaxViewRoot.processEvents(FacesContext, EventsQueue, boolean) line: 321
          AjaxViewRoot.broadcastEvents(FacesContext, PhaseId) line: 296
          AjaxViewRoot.processPhase(FacesContext, PhaseId, InvokerCallback) line: 253
          AjaxViewRoot.processApplication(FacesContext) line: 466
          InvokeApplicationPhase.execute(FacesContext) line: 82
          InvokeApplicationPhase(Phase).doPhase(FacesContext, Lifecycle, ListIterator<PhaseListener>) line: 100
          LifecycleImpl.execute(FacesContext) line: 118
          FacesServlet.service(ServletRequest, ServletResponse) line: 265
          ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 290
          ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 83
          IdentityFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 40
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          MultipartFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 90
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          ExceptionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 64
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          RedirectFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 45
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          ConfigurableXMLFilter(BaseXMLFilter).doXmlFilter(FilterChain, HttpServletRequest, HttpServletResponse) line: 178
          Filter(BaseFilter).handleRequest(HttpServletRequest, HttpServletResponse, FilterChain) line: 290
          Filter(BaseFilter).processUploadsAndHandleRequest(HttpServletRequest, HttpServletResponse, FilterChain) line: 368
          Filter(BaseFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 495
          Ajax4jsfFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 56
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          LoggingFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 60
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          HotDeployFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 53
          SeamFilter$FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 69
          SeamFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 158
          ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 235
          ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
          ReplyHeaderFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 96
          ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 235
          ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 206
          StandardWrapperValve.invoke(Request, Response) line: 235
          StandardContextValve.invoke(Request, Response) line: 191
          SecurityAssociationValve.invoke(Request, Response) line: 190
          NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 433
          JaccContextValve.invoke(Request, Response) line: 92
          SecurityContextEstablishmentValve.process(Request, Response, HttpEvent) line: 126
          SecurityContextEstablishmentValve.invoke(Request, Response) line: 70
          StandardHostValve.invoke(Request, Response) line: 127
          ErrorReportValve.invoke(Request, Response) line: 102
          CachedConnectionValve.invoke(Request, Response) line: 158
          StandardEngineValve.invoke(Request, Response) line: 109
          CoyoteAdapter.service(Request, Response) line: 330
          Http11Processor.process(Socket) line: 829
          Http11Protocol$Http11ConnectionHandler.process(Socket) line: 598
          JIoEndpoint$Worker.run() line: 447
          Thread.run() line: 619
      


        • 1. Re: Problem using Seam identity management with User -> Role link table
          lvdberg

          Hi,


          take a look at Hibernate-Envers which is intended for auditing-purposes. You can add a seam specific listener to add for instance the user who makes modifications.


          Works very nice if you can plan to join and leave a role different times, You just check the audit table and it's much simpler than creating complex non.domain specific relations in your model


          Leo