Lesson Materials

Our lesson uses backend code from this repository. If you want to follow along in this lesson, please git clone with the line below and run Main.java to use localhost:

git clone https://github.com/John-sCC/Roles_BE.git

Person and PersonRole Relationship

Person Object

(See Person.java)

The Person object is a POJO, which stands for “Plain Old Java Object.” Essentially, it’s a Java object with no special restrictions or requirements. It contains business logic and data for modeling entities.

Of the attributes of the object Person, one is roles, which is a Collection of PersonRole objects. These are the roles that we go over in this lesson.

// FULLY IMPLEMENTED!
@ManyToMany(fetch = EAGER)
private Collection<PersonRole> roles = new ArrayList<>();

As a quick recap of SQL concepts:

  • @ManyToMany establishes that Person and PersonRole have a Many-to-Many relationship with each other (the same role can be assigned to many Person objects, and multiple Person object can be assigned to many roles).
  • fetch = EAGER establishes that, when a Person object is fetched, its roles should be fetched immediately at the same time. If it was instead fetch = LAZY, the PersonRole objects would only be fetched explicity, separate from the Person object.

PersonRole Object

(See PersonRole.java)

The PersonRole object is another POJO with its own entities separate from the Person object. They are assigned to each other. In preparation for the lesson, we added an argument constructor and an initializer method.

public class PersonRole {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique=true)
    private String name;

    public PersonRole(String name) {
        this.name = name;
    }

    public static PersonRole[] init() {
        PersonRole student = new PersonRole("ROLE_STUDENT");
        PersonRole teacher = new PersonRole("ROLE_TEACHER");
        PersonRole admin = new PersonRole("ROLE_ADMIN");
        PersonRole[] initArray = {student, teacher, admin};
        return initArray;
    }
}

Initializing PersonRole

Now that we have an initializer for the PersonRole object, we add it to the ModelInit.java file as shown below. (Modified slightly to emphasize roles.)

public class ModelInit {  
    // ...declarations...
    @Autowired PersonRoleJpaRepository roleRepo;

    @Bean
    CommandLineRunner run() {  // runs when the application starts
        return args -> {
            // ...jokes...

            // initializing person roles
            PersonRole[] personRoles = PersonRole.init();
            for (PersonRole role : personRoles) {
                PersonRole existingRole = roleRepo.findByName(role.getName());
                if (existingRole != null) {
                    // role already exists
                    continue;
                } else {
                    // role doesn't exist
                    roleRepo.save(role);
                }
            }

            // initializing person objects
            Person[] personArray = Person.init();
            for (Person person : personArray) {
                //findByNameContainingIgnoreCaseOrEmailContainingIgnoreCase
                List<Person> personFound = personService.list(person.getName(), person.getEmail());  // lookup
                if (personFound.size() == 0) {
                    personService.save(person);  // save
                    // ...notes...
                    // adding the student role to each initial person
                    personService.addRoleToPerson(person.getEmail(), "ROLE_STUDENT");
                }
            }
            // for lesson demonstration: giving admin role to Mortensen
            personService.addRoleToPerson(personArray[4].getEmail(), "ROLE_ADMIN");
        };
    }
}

The code is written so that, if the SQL database has been emptied, the roles will be recreated, but if it hasn’t been, they won’t be created a second time, which would cause an error (since the names would be repeats).

We gave one of the test Person objects, “John Mortensen,” the “ROLE_ADMIN” role. This will be used in conjunction with roles-based security.

Viewing Person and PersonRole in SQL

Now that the roles have been created and assigned, they can be viewed in the SQL table in two different ways that offer different information.

If you open the sqlite.db and look at the “person_role” (singular) table, you’ll see something like this:

This shows each role and its corresponding ID. It works basically the same way as the “person” table.

The second table has the title “person_roles” (plural). This type of table is called a “join table,” and it represents Many-to-Many relationships by showing the corresponding IDs of objects with relationships in pairs.

All Person objects other than the one with ID 5 only have a relationship to PersonRole ID 1, which is the “ROLE_STUDENT” role given when initialized. The Person with the ID 5 was given both “ROLE_STUDENT” and “ROLE_ADMIN,” so he has two different relationships shown.

Using Roles for Security

[TO BE FINISHED TOMORROW!] (AJ, EKAM?)

Reference: See the “Security with Roles” section of this issue

Frontend Application

MVC on Localhost

Login on Blog

JWT