• Welcome to KonaKart Community Forum. Please login or sign up.
 

Overriding the client-side productmanager (External product catalog)

Started by Kim.Zeevaarders, May 26, 2011, 07:36:08 am

Previous topic - Next topic

Kim.Zeevaarders

Hello,

We are going to rebuild the old webshop of a University in the Netherlands with Konakart.

On of the complications is that the products of the University (courses, etc.) are persisted in 2 different legacy databases (Oracle).

Right now we are thinking about the architecture of the solution and are considering two options:

1. The first option is periodically synchronizing these legacy databases with the konakart database usin the xml_io tool or by creating some custom interface using the Konakart API's.
2. Another option is that we only registrate a reference to the products in Konakart (id in products_table), so we can use alle functionality of konakart, but if the content of the product needs to be used we get this data from the legacy database. Our initial thought was to subclass the client-side productmanager and override the relevant methods where necessary.

I saw in the API examples that you can create your own custom product manager and register this new manager in the konakart.properties file. There is only one problem: this concerns the server-side product manager. We need to subclass the client-side product manager because this is returned by the KKAppEng.

My question is therefore as follows:
- Is option 2 a viable one? If not could you please explain where it will go wrong?
- If it is viable, is it possible to subclass the client-side product manager and let the KKAppEng use this? Is it, for example, possible to subclass the KKappEng and let the engine return our custom product manager when the method getKKAppEngine is invoked?

I would like to hear your thoughts about the conceptual idea and, if it's possible, receive some guidelines for doing this.

Many thx in advance,

Kim Zeevaarders








trevor

I recommend building a small utility using the KK admin APIs that synchronizes the KK database with the legacy databases at regular intervals or whenever the legacy data changes. In this way you'll have all of the data within KK and will be able to use all of the available product search and sort functionality. i.e. If you use the enterprise version of KK you'll be able to take advantage of the SOLR search engine and the suggested search functionality.

Kim.Zeevaarders

Hi Trevor,

First of all, thanks for the quick response.

I know from other posts about external product catalogs that you guys recommend synchronization over customization, so in that aspect I inderstand your answer.

But the problem here is that we don't want to replicate productdata and want the legacy systems to remain master of the data.

So it basically comes down to this: which of the 2 options will be the least complex and will be more future proof? Is my second option even possible?

Could you point out what functionallity we will be missing when we only store a reference to the products in konakart (whereas the content is coming from the legacy systems)? Does this only mean we cannot use the search engine (we are using the enterprise edition) or are there other farstretching limitations?

Don't get me wrong, if u guys say it's better to synchronize we are definitely going to do this. But we would like to make a well-judged decision about this when defending this decision to our customer.

Regards,

Kim






trevor

A lot depends on how your store front application works and the user experience you want to give to your customers. i.e. If you want to allow them to search for products, sort them by various attributes, use product tags to categorize them etc. then we need the data within our database in order to be able to query it.

Another problem that often comes up with just storing a reference, is performance, so you have to be careful to store enough descriptive data in the KK database in order to be able to display a list of products, and only look up from the legacy database if a customer asks for more details.

If you were to take the reference approach, I think that a good way of doing it would be to use our custom engine and to customize the getProduct* API calls to fill the product objects with external data before returning them to the client engine .

Kim.Zeevaarders

Trevor,

Again thank for the quick response.

I just read the "Customization of the KonaKart Engines" part in the user guide and I think this is exactly what you mean.

I'm going to try to make a proof of concept to see how difficult this is and what limitations arise when using this approach.

My opinion is that we indeed should synchronize, but I will check this option also to come to a well-judged decision...

I will output my results in this topic so that it might be of some use for the community.

Regards,

Kim

trevor

Yes, the custom engine is a good way of adding functionality since the API calls tend to be very stable between releases so you should have no problems upgrading.

I look forward to reading about your results.

Kim.Zeevaarders

Trevor,

Could you please enlighten me on the following:

Does the productmanager (kkAppEng.getProdMgr()) invoke the kkEngApp methods (like getProduct()) to get his work done? If not, then how to modify the behaviour of the product manager? Say, for example, that I would like to intervene in the fetchNewProductsArray method of the productmanager that is called when you login to Konakart. In that case I would like to fetch the productreferences from the kk database and then add the legacy data to them before storing the products in the newProductsArray of the productmanager.

Is this possible? The reason why I am asking this is that I don't know when the kkEngApp methods will be called. I am now customizing the getProduct method of the custom engine but I have no clue when it will be called. I know that i can call the methode getProducts on the engine directly where I need it but i've got a feeling that is not the idea. Am I Right?

Regards,

Kim

Kim.Zeevaarders

I just found out one minute after posting this thread that there is a difference between the kkEng and the kkAppEng. So my assumption is that the kkAppEng delegates call to the kkEng. Is this right?

If not could you please tell me how the differenct engines work together?

Thx,

Kim

Kim.Zeevaarders

Trevor,

Sorry for the multiple posts i've posted. It seems you cannot edit a post.

I found out that you can get the kkEng by calling kkAppEng.getEng() so please ignore my previous post.

Next time I will take a deeper look before posting stupid questions :)

Thx,

Kim


trevor

Take a look at http://www.konakart.com/product/technical-details .

The AppEng does invoke the Eng to get his work done. You will be customizing the Eng API calls. As long as the API calls keep on returning ProductIf objects the AppEng will continue working as is.  You customization code should just fill in the attributes of the Product objects from your external sources. You should customize all API calls that return Products.

Not everyone uses the AppEng since it is quite specific to a certain type of eCommerce application. For example, many customers that integrate KK into CMS applications, make calls directly to the engine.

Kim.Zeevaarders

Trevor,

It makes total sense now.

The kkAppEng delegates to the kkEng. This also means that the Productmanager uses the kkEng.

So modifying the kkEng changes the behaviour of the kkAppEng, including the behaviour of the different managers (basketmanager, productmanager, etc)

I'll come back to you on this as soon as I get my proof of concept up and running.


Thx for taking the time to reply,

Kim

Kim.Zeevaarders

Trevor,

I've started with overriding some of the methods in the kkCustomEng. Furthermor I've added a System.out.println(<methodname>) statement in all methods of the kkCustomEng class to see which methods are called during execution.

In my simple testcase I have a product stored in Konakart with only the not-null fields filled. My intention is to get all content for this product from another system.

So I overrode the getProduct and getProductWithOptions using the customEngine Framework. In these methods I simply add (hardcoded) information to the otherwise nearly empty product in the kk database.

When I press AddToCart (on this product) on the mainpage and start debugging I indeed see that a call to kkAppEng.getProductMgr().fetchSelectedProduct(new Integer(prodId).intValue()) is delegated to the getProductWithOptions method of the custom engine (this happends in the action AddToCartFromProdIdAction). The product is then retrieved with kkAppEng.getProductMgr().getSelectedProduct() and does indeed contain the added properties I programmed in getProductWithSelectedOptions.

However now comes the problem that I was already expecting. Further in the code the selectedProduct is added to a BasketIf object and added to the customerbasket (kkAppEng.getBasketMgr().addToBasket(b, /* refresh */false)). Only the id and quantity (1) of the product are set as a property of the basket object.

In the following action, ShowCartItemsAction, the basketitems are again updated and retrieved for showing on the page:

BasketIf[] items = kkAppEng.getEng().updateBasketWithStockInfoWithOptions(
                        kkAppEng.getCustomerMgr().getCurrentCustomer().getBasketItems(),
                        kkAppEng.getBasketMgr().getAddToBasketOptions());


However, the product seems to be reloaded from the database and has lost all of the added properties I added in getSelectedProductWithOptions. Looking back at the creation of the basket and the adding by the basketMgr I tried to do two things to prohibite this:
- I set not only the productId of the basketIf object, but also the entire product object (b.setProduct(selectedProd))
- I set the property true to false when calling the basketMgr.addToBasket(b, false) in the hope there wil no reload.

Both options do not work and the product is always reloaded from the database.

So the only thing I can do now is desig a custom BaksetMgr so that I can override the relevant methods like kkAppEng.getEng().updateBasketWithStockInfoWithOptions and  kkAppEng.getCustomerMgr().getCurrentCustomer().getBasketItems(). This is not difficult since both methods return an array of BasketIf objects which contain the products I need to fill with legcy data.

My question however is if you guys could tell me if this is the way to go when customizing the engine and if i'm on the right way using this approach. If not could you guys give me some of your insights on this matter and some of the best practices that should be followed? Perhaps a sort of strategy to follow?

Thx in advance,

Kim

trevor

Where are you seeing the reloaded product without the properties ? Maybe you haven't specialized the API call that was used to fetch it ? There are quite a few API calls that return products.

Kim.Zeevaarders

Trevor,

You're right. The method updateBasketWithStockInfoWithOptions is called on the engine and thus overridable by me. I thought it was a method of the basketMgr.

Is it true that if I customize ALL relevant productmethods of the engine that I don't have to create custom managers (because they rely on the engine methods)? For example will the call to  kkAppEng.getCustomerMgr().getCurrentCustomer().getBasketItems() return the legacy filled products I coded in the custom engine methods (on the condition I overrode all relevant product methods)?

Thx for the help.

Regards,

Kim






trevor

The managers do call each other. i.e. Various managers call the ProductManager to get product information so there may be some cases where you'll need to go to the ProductManager.

It's rather difficult to list all dependencies of all of the API calls so I suppose the safest bet could be to customize at the ProductManager level although we don't guarantee that these internal methods won't change between releases so there may be a bit more work to do when upgrading.