Autowiring a DAO into a domain object

autowired, dao, java, spring, spring-mvc

Solution

I'm not saying that I agree with injecting DAOs into domain instances....but

You can wire your DAO into you domain object. But you'll have to declare your domain object in your spring application-context and obtain new instances from Spring NOT using `new`. Make sure that you use the prototype scope! You don't want to be getting the same singleton instance everytime!

Really this logic that you want to implement belongs in a service which is injected with the DAOs that it requires.

Perhaps you could have a service like:

@Service
public class RibbonServiceImpl implements RibbonService

  @Autowired
  private RibbonDAO ribbonDAO;

  public boolean isEarned(Ribbon ribbon, 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;
  }  

Problem

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

Original source

Related problems