jpapicketlink

How to map existing JPA entities to PicketLink


I am trying to migrate a Seam 2 app to CDI and use PicketLink for security. After all the reading and researching, it seems like all the examples are having one to one mapping between PicketLink model and the backend entity. e.g. Account to AccountEntity, Partition to PartitionEntity. Since I already have entities in place representing identity model, I am stuck on trying to map them to PicketLink. Here is what I have:

@MappedSuperClass
public class ModelEntityBase implement Serializable {
    @Id @Generated
    Long id;
    Date creationDate;
}

@Entity
public Account extends ModelEntityBase {
    String username;
    String passwordHash;
    @OneToOne(mappedBy = "account")
    Person person;
}

@Entity
public Person extends ModelEntityBase {
    String name;
    String email;
    @OneToOne
    @JoinColumn(name = "account_id")
    Account account;
}

Two entities (plus a super class) representing a single identity model in PicketLink, e.g. stereo type User.

Based on this why IdentityType id is String not Long, I tried to add a new Entity in:

@Entity
@IdentityManaged(BaseIdentityType.class);
public class IdentityTypeEntity implement Serializble {
    @Id @Identifier
    private String id;

    @OneToOne(optional = false, mappedBy = "identityType")
    @OwnerReference
    private Account account;

    @IdentityClass
    private String typeName;

    @ManyToOne @OwnerReference
    private PartitionEntity partition;
}

I've tried a few different ways with the annotation and model classes. But when using IdentityManager.add(myUserModel), I just can't get it to populate all the entities. Is this even possible?


Solution

  • Got help from Pedro (PicketLink Dev). Post the answer here to help others. This is the model class I ended up using.

    @IdentityStereotype(USER)
    public class User extends AbstractAttributedType implements Account {
        @AttributeProperty
        private Account accountEntity;
        @AttributeProperty
        @StereotypeProperty(IDENTITY_USER_NAME)
        @Unique
        private String username;
        @AttributeProperty
        private boolean enabled;
        @AttributeProperty
        private Date createdDate;
        @AttributeProperty
        private Date expiryDate;
        @AttributeProperty
        private Partition partition;
        // getter and setter omitted
    }
    

    And created a new entity to map to this model:

    public class IdentityTypeEntity implements Serializable {
        @Id
        @Identifier
        private String id;
    
        @OneToOne(optional = false, mappedBy = "identityType",
            cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @AttributeValue
        // @NotNull
        private HAccount accountEntity;
    
        @IdentityClass
        private String typeName;
    
        @ManyToOne
        @OwnerReference
        private PartitionEntity partition;
    
        @AttributeValue
        private String username;
    
        @AttributeValue
        // @Transient
        private boolean enabled;
    
        @AttributeValue
        private Date createdDate;
    
        @AttributeValue
        private Date expiryDate;
    }
    

    PL can map property with @AttributeProperty to entity property with @AttributeValue. But it can only map to one entity. Therefore there is no way to map, say User and its properties over to Account and Person. But you can have the entity (in my case accountEntity) in the model. I also have to duplicate a few fields in the new IdentityTypeEntity and my existing Account entity (username, eanbled, createdDate) because PL requires these. Use a @PrePersist and similar to sync them.