Reputation: 1393
I have an app used in 3 different countries. It is almost all the same, with a few country dependent exceptions, for example an order would have salesTax in USA, but not in the UK. Each country has its own database, completely separate to each other, with slight differences in the table structure for these country specific properties. The table names are always identical, as are the columns that all countries share; it is only the extra columns that make them different.
Currently as a result I actually have 3 separate applications, with about 80% identical code. Every time I develop something, I need to copy it into each individual application which is a bit laborious.
My plan is to try and have a global application, and then extend this with the 3 much smaller country specific ones.
For my services and daos this can be handled by my interfaces being global, and any implementations that vary between the apps being local. The local apps will pull in the global as a dependency.
However, my problem is with the business objects. With the order as an example again, many of my services and daos use the Order object, and they would be global since the code is identical across countries. So I need to have some sort of GLOBAL Order object. But I also want to make sure that depending on the country, the extra properties are available and persisted if I go and save them again.
As an example, I have a service that just checks the tracking of an order and marks it as Delivered. This service is global, so would have access to the GLOBAL Order object. it would call orderDao.getOrder(id) thanks to the orderDao interface being global. The orderDaoImpl would be local, so the getOrder(id) method would actually return a localized Order instance, complete with extra fields. When this is passed up through the layers it reaches the tracking service again, which is expecting a GLOBAL Order, meaning the localized fields are not available (this is OK because this trackingService doesn't care about them, if it did, the implementation would be localized).
When I update the status of this GLOBAL Order I need to make sure that when it gets saved the localized properties are not lost.
So my big question is how can I make this work?
Option 1: Is there any way for me to define some "selective transiency"? So I have a single Java Object with all possible properties. When it is used in each application, if any of those properties don't exist in the database table just ignore it and carry on.
OR
Option 2: Is there a way for me to use some abstract/interfaced class that could be used at both global and local level, with local apps automatically casting the object as the implemented subclass?
It is worth pointing out that the GLOBAL app as such would never actually be run by itself, it would only ever be used within the local apps. But obviously cant have references to the local classes.
Cheers for any assistance.
Upvotes: 4
Views: 646
Reputation: 1393
OK. I think I have come up with the least elegant, but workable solution to this.
The problem is allowing my global apps to know about the local Business Objects such as Orders, but not having them mapped to columns that may not exist in each country.
So, I have included them in my Global project, and included every possible attribute, and getters/setters.
I then ALSO include them in my local projects with only the fields needed in that particular country.
Since the global apps are never actually used by themselves, whenever I build the library using maven, I exclude any of the business objects that are in my local projects. So when the local then includes it as a dependency there are no conflicts, and only the local version of these objects are included, meaning Hibernate doesn't complain about missing columns.
Not clean, but it works!
Upvotes: 0
Reputation: 5377
Might not be the most elegant solution, but you could make a global order class that isn't mapped as an @Entity
and include it in your regional orders with @Embedded
class GlobalOrder {
@Column(name = "total")
private Integer orderTotal;
...
}
@Entity
@Table("emeaorder")
class EMEAOrder {
@Embedded
private GlobalOrder globalOrder;
@Column(name = "tax")
private Integer euSalesTax;
...
}
Upvotes: 2