I'm integrating with a 3rd party vendor that has Users
and Organizations
in it. My tool is a user administration tool that allows us to store information in our local database about the Users
and Organizations
that we manage in the 3rd party vendor. So the Users
and Organizations
are stored in the 3rd party vendor as well as our database (we act as the middle man sort of). I'm at a crossroads with some ideas and would like to hear what others thought of the following problem and my solution.
Before I dive in, we're using Grails 2.4.4
One use case for the tool is creating a User
. We create the user in the 3rd party vendor via an API call, and then we store information about that user in our database. There are many uses cases like this and there are 3 fields that are always in common between them, an API Token
a Data Center ID
and an Organization ID
. These 3 fields are required for just about every API call we make to our 3rd party vendor and most of the Controller
Actions
result in an API call being made. For this reason, I had the idea to make a "Common" Command Object
with these 3 fields on it that can be extended by another Command Object.
@Validateable
class CommonRequestCommand {
String apiToken
String dataCenterId
String orgId
static constraints = {
apiToken nullable: true
dataCenterId nullable: true
}
}
@Validateable
class UserCreateCommand extends CommonRequestCommand {
String email
String firstName
String lastName
}
There is one catch to this idea. The apiToken
and dataCenterId
are mutable (which I believe immutability is strongly suggested by Spring). It's possible that the apiToken
and/or dataCenterId
fields are supplied by the client/UI, or they might not be (orgId will always be supplied from the UI form). If they are not supplied, we query our database for them. If they do not exist in our database, then we throw an error. They almost always will NOT be supplied. To do that, I change the CommonRequestCommand
to override the Getter
methods and look up the API Token
or Data Center ID
if they are not provided
@Validateable
class CommonRequestCommand {
private String apiToken
private String dataCenterId
String orgId
public String getApiToken() {
if(apiToken == null){
Organization org = Organization.findById(orgId)
if(org == null){
throw new OrganizationException("Organization not found")
}
apiToken = org.apiToken
}
return apiToken
}
public void setApiToken(String apiToken){
this.apiToken = apiToken
}
public String getDatacenterId(){
if(this.dataCenterId == null){
Organization org = Organization.findById(orgId)
if(org == null){
throw new OrganizationException("Organization not found")
}
dataCenterId = org.dataCenterId
}
return dataCenterId
}
public void setDatacenterId(String dataCenterId){
this.dataCenterId = dataCenterId
}
}
My Question:
Do you think this is an appropriate design? I believe the biggest drawback to this is that the CommonRequestCommand
is mutable.
Brainstorming a few other ways:
- Drop the
CommonRequestCommand
and inheritance of command objects and instead create anInterceptor
that creates a POGOCommonRequestObject
and stores it in therequest
scope. Then in the controller, I pass both theUserCreateCommand
object and theCommonRequestObject
to theservice
layer. - Just pass the 3 fields through the
params
scope and don't worry about creating theCommonRequestCommand
or aninterceptor
. Instead, every method in theservice layer
would have an additional 3 arguments for these fields.