Page 1 of 1

Extending Sku Entity

Posted: Wed Feb 06, 2013 1:02 pm
by pccfrmvns
Hi,

I am trying to extend an BL Sku entity. I've created an interface(MySku) and extended the SkuImpl in MySkuImpl class and implemented MySku.

Code: Select all

public interface MySku {

   public void setRentalPrices(Map<Integer, BigDecimal> rentalPrices);
   
   public Map<Integer, BigDecimal> getRentalPrices();
}


Code: Select all

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name="MY_SKU")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
public class MySkuImpl extends SkuImpl implements MySku{

   /**
    *
    */
   private static final long serialVersionUID = -518974372567977433L;
   @Transient
   protected static final Log LOG = LogFactory.getLog(TbrSkuImpl.class);
   
   @Resource(name="myRentalEngine")
   @Transient
   protected IRentalEngine rentalEngine;
   
   @Transient
   protected Map<Integer, BigDecimal> rentalPrices = new HashMap<Integer, BigDecimal>();
   

   @Override
   public void setRetailPrice(Money retailPrice) {
      super.setRetailPrice(retailPrice);
      
      //Set Rental price after setting Retail Price
      try {
         rentalPrices = rentalEngine.calculateAllRentals(retailPrice.getAmount());
      } catch (RentalServiceException e) {
         LOG.warn("Error in rental price calculation for retail price: "+retailPrice.getAmount()+" "+e.getMessage());
         //e.printStackTrace();
      }
   }
   
   public void setRentalPrices(Map<Integer, BigDecimal> rentalPrices) {
      this.rentalPrices = rentalPrices;
   }
   
   public Map<Integer, BigDecimal> getRentalPrices(){
      return this.rentalPrices;
   }
   
}


I've added this implementation class in persistence.xml and overrided Sku entity by in application context as

Code: Select all

<bean id="org.broadleafcommerce.core.catalog.domain.Sku" class="com.mycompany.core.catalog.domain.MySkuImpl" scope="prototype"/>


Now I am trying to access the rentalPrices field by Spring EL expression. in listProducItem.html. I get exception as below

Code: Select all

Field or property 'rentalPrices' cannot be found on object of type 'org.broadleafcommerce.core.catalog.domain.SkuImpl'


Please help.

Re: Extending Sku Entity

Posted: Wed Feb 06, 2013 3:38 pm
by phillipuniverse
How did you add the Sku to begin with? Via the admin? There might be a problem in the admin when instantiating Skus; it's possible that we don't instantiate the correct subclass. I assume there is no corresponding entry in your MY_SKU table?

Re: Extending Sku Entity

Posted: Wed Feb 06, 2013 4:06 pm
by pccfrmvns
My BLC_SKU table was prepolulated via SQL scripts. I am not using admin module for now. site module only is being used. I was able to extend Order entity but I am not to extend Sku entity in the same way. I also tried to implement the SKu interface completely by copying the implementation from SkuImpl class. My extended entity has transient fields only.

Yes MY_SKU table is created and there is no entry in MY_SKU for now. There won't be any entry in MY_SKU table except SKU_ID as my fields are transient and are only calculated from sku price.

My BLC version is 2.0.0-M1-1.

Re: Extending Sku Entity

Posted: Wed Feb 06, 2013 4:33 pm
by phillipuniverse
The problem with your implementation is that Hibernate will always pull back instances of SkuImpl (and not MySkuImpl) because you do not have a primary key join in the corresponding MY_SKU table. Hibernate then assumes that you would like instances of SkuImpl and will only return those instances to you.

If you are only using transient fields on your extended entity then it sounds like you might be trying to solve this the wrong way. Really, the only reason you would want to extend SkuImpl in the first place would be to add additional database columns or additional joins, not in the way that you are attempting to use it. We also do not typically inject other services into entities as you have done. I'm actually fairly positive that this will not be properly wired at all when it comes back from a query, as it does not communicate with Spring at all to pull back the entity.

You have an interesting use case, I'm not sure at the moment how I would tackle it. Perhaps via a custom Thymeleaf processor to show the rental prices for that Sku?

Re: Extending Sku Entity

Posted: Sun Feb 10, 2013 11:22 am
by pccfrmvns
Hi Phillip,
Thank you for the answer.
Please explain how can I create primary key join explicitly in MY_SKU table. When I start site I see a table with name MY_SKU created and it already has SKU_ID column. Which I believe means hibernate is aware of MySkuImpl class.

But the Products when loaded from DB only have SkuImpl objects and not MySkuImpl objects.

As you suggested I am not injecting entities in MySKuImpl now. But, I need a transient field in Sku which is based on retail price of Sku and is not persisted in db. I find it logical to have transient rental price as a property of Sku. I am willing to set this transient field in controller. This way I need to code less.

What is different with Sku entity as compared to other entities. As I've extended OrderImpl before exactly like this.

Re: Extending Sku Entity

Posted: Sun Feb 10, 2013 8:57 pm
by phillipuniverse
There isn't really anything different between how you've extended Sku and how you've extended Order. The difference is in how they are created to begin with. For Order, it is created by the system automatically, and you have configured to create your instance of Order (MyOrderImpl) vs just the normal Broadleaf Order (OrderImpl). So if a Customer created an order, the database would look like this:

BLC_ORDER
ORDER_ID | DATE_CREATED | STATUS ...
1| 2/10/13 | IN_PROCESS

MY_ORDER
ORDER_ID | CUSTOM_FIELD_1 | CUSTOM_FIELD_2 ...
1 | somedata | somedata

So now, when you tell Hibernate "give me all of the Orders in the system" it checks the BLC_ORDER table as well as any subclasses. In this scenario, it Hibernate sees that there is a corresponding foreign key in the MY_ORDER table, so the instance it gives back is MyOrderImpl and not OrderImpl.

Now let's equate this to your scenario in the Sku table. Your data probably looks like this:

BLC_SKU
SKU_ID | NAME | DESCRIPTION ...
1 | test | some_descr

MY_SKU
SKU_ID (no other columns)
--


So notice how you have an ID defined in the BLC_SKU table, but no foreign key for ID 1 in the MY_SKU table. Now, when you tell Hibernate "give me back all the Skus" it goes and looks at the BLC_SKU table, sees the ID of 1 there, recognizes that while you have a MY_SKU table which is a subclass of BLC_SKU there isn't a foreign key reference to ID 1, so it then returns you an instance of SkuImpl. If you instead wanted to get back a MySkuImpl, you would need this:

BLC_SKU
SKU_ID | NAME | DESCRIPTION ...
1 | test | some_descr

MY_SKU
SKU_ID (no other columns)
1


Now, Hibernate will pull back a MySkuImpl.

For a final more complete example, consider this example:
BLC_SKU
SKU_ID | NAME | DESCRIPTION ...
1 | test | some_descr
2 | test2
3 | test3
4 | test4
5 | test5

MY_SKU
SKU_ID (no other columns)
1
3
5


And you did this:

Code: Select all

List<Sku> skus = catalogService.findAllSkus();
for (Sku sku : skus) {
   System.out.println(sku.getClass().getName());
}

Then the output would be:

Code: Select all


com
.mycompany.core.catalog.domain.MySkuImpl;
org.broadleafcommerce.core.catalog.domain.SkuImpl
com
.mycompany.core.catalog.domain.MySkuImpl;
org.broadleafcommerce.core.catalog.domain.SkuImpl
com
.mycompany.core.catalog.domain.MySkuImpl;

Re: Extending Sku Entity

Posted: Wed Feb 13, 2013 9:50 am
by pccfrmvns
Hi Pillip,
Thank you very much for the elaborate answer. :)
This solves my problem. For now, I've modified the DB script to insert foreign keys in extended table. And now MySku instances are being created. :D