title: Business logic in domain objects
body: <p>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.</p>
  
  <p>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.</p>
  
  <p>In the way I coded it, <code>Ribbon</code> is a simple interface:</p>
  
  <pre><code>public interface Ribbon {
      public void setId(int id);
      public int getId();
      public String getTitle();
      public void setTitle(String title);
      public boolean isEarned(User user);
  }
  </code></pre>
  
  <p><code>RibbonJpa</code> is an abstract class that implements the <code>Ribbon</code> interface, avoiding the definition of the <code>isEarned()</code> method:</p>
  
  <pre><code>@Entity
  @Table(name = "ribbon")
  @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
  @DiscriminatorColumn(name = "ribbon_type")
  public abstract class RibbonJpa implements Ribbon {
      @Id
      @Column(name = "id", nullable = false)
      int id;
  
      @Column(name = "title", nullable = false)
      private String title;
  
      @Override
      public int getId() {
          return id;
      }
  
      @Override
      public void setId(int id) {
          this.id= id;
      }
  
      @Override
      public String getTitle() {
          return title;
      }
  
      @Override
      public void setTitle(String title) {
          this.title = title;
      }
  }
  </code></pre>
  
  <p>You can see I define the inheritance strategy as <code>SINGLE_TABLE</code> (since I have to code like 50 ribbons and I don't need additional columns for any of them).</p>
  
  <p>Now, a specific ribbon will be implemented like this:</p>
  
  <pre><code>@Entity
  public class FirstUsersRibbon extends RibbonJpa implements Ribbon {
      public FirstUsersRibbon() {
          super.setId(1);
          super.setTitle("First 2,000 users registered to the website");
      }
  
      @Override
      public boolean isEarned(User user) {
          // My logic to check whether the specified user has won the award
      }
  }
  </code></pre>
  
  <p>This code works fine, the tables are created in the database in the way I expect (I use DDL generation in my local environment).</p>
  
  <p>The thing is, it feels wrong to code business logic in a domain object. Is it good practice? Can you suggest a better solution? Also, I'm not able to Autowire any DAOs in the entity (<code>FirstUsersRibbon</code>) and I need them in the business logic (in this case, I need a DAO to check whether the user is in the first 2,000 users registered to the website).</p>
  
  <p>Any help very appreciated.</p>
  
  <p>Thank you!</p>