I am coding a ribbon/achievements system for a website and I have to write some logic for each ribbon in my system. For example, you could earn a ribbon if you're in the first 2,000 people registering to the website or after 1,000 post in the forum. The idea is very similar to stackoverflow's badges, really.
So, every ribbon is obviously in the database but they also need a bit of logic to determine when a user has earned the ribbon.
In the way I coded it, Ribbon
is a simple abstract class:
@Entity
@Table(name = "ribbon")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "ribbon_type")
public abstract class Ribbon
{
@Id
@Column(name = "id", nullable = false, length = 8)
private int id;
@Column(name = "title", nullable = false, length = 64)
private String title;
public Ribbon()
{
}
public abstract boolean isEarned(User user);
// ... getters/setters...
}
You can see I define the inheritance strategy as SINGLE_TABLE
(since I have to code like 50 ribbons and I don't need additional columns for any of them).
Now, a specific ribbon will be implemented like this, for example:
@Entity
public class First2000UsersRibbon extends Ribbon
{
@Autowired
@Transient
private UserHasRibbonDao userHasRibbonDao;
public First2000UsersRibbon()
{
super.setId(1);
super.setTitle("Between the first 2,000 users who registered to the website");
}
@Override
public boolean isEarned(User user)
{
if(!userHasRibbonDao.userHasRibbon(user, this))
{
// TODO
// All the logic to determine whether the user earned the ribbon
// i.e. check whether the user is between the first 2000 users who registered to the website
// Other autowired DAOs are needed
}
else
{
return true;
}
return false;
}
}
The problem is that userHasRibbonDao
is null inside the isEarned()
method, so a NullPointerException
is thrown.
I thought that having DAOs autowired into domain objects was wrong, but in this topic they told me that it's the correct approach (Domain-Driven Design).
I shared a non-working very simple example on GitHub: https://github.com/MintTwist/TestApp (remember to change the connection details in /WEB-INF/properties/jdbc.properties and to import the test_app.sql script)
Any help very appreciated.
Thank you!
Update - Reading the first answers, it seems like my approach is completely wrong. How would you ideally structure the code given that there may be 50-70 different ribbons? Thanks