7
We have a system, which I will call A, which serves some customers. We are now performing the first integrations with the internal systems (ERP) of these customers. When we make, for example, a request to the web service of System A, it should map this request to a specific web service integration (made available by the client), so the data will stop directly in the database of the Erps of each client.
The flow can be summarized in the following:
Request Web Service System The Request Client Integration Web Service Client Database
However, not all customers have or will even have integration with their internal systems, so the flow to them remains this:
Request Web Service System The Database System A
Currently, the Web Service of System A is made in Java, using Jersey and the REST Standard.
For each Resource class, which is where Jersey endpoint mappings exist, there is also a specific Service class. In the services classes are all existing business logic. Finally, the trio is completed with a DAO class, which is responsible for the CRUD of the data in the database.
Thus, given any functionality in System A, the following classes could exist:
RESOURCE
@Path("/funcionalidade")
@Consumes(MediaType.APPLICATION_JSON + ";charset=utf-8")
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public class FuncionalidadeResource {
private final FuncionalidadeService service = new FuncionalidadeService();
@GET
@Path("/exemplo")
public String getExemplo() {
return service.getExemplo();
}
}
SERVICE
public class FuncionalidadeService {
private final FuncionalidadeDao dao = new FuncionalidadeDao();
public String getExemplo() {
// Lógica de negócios necessária aqui
return dao.getExemplo();
}
}
DAO
public class FuncionalidadeDao {
public String getExemplo() {
// Consulta o banco de dados aqui
return "Um dado buscado do banco";
}
}
All Services and Daos have interfaces, which were hidden here for brevity.
With this, my question is the following, how to make sure that for certain clients (those who have integration) the request is diverted to their web services and never actually use the DAO of System A?
Another point that adds complexity: a single functionality can have numerous methods in your Resource, but not necessarily all will be integrated. This means that: for the same functionality, in some requests the search must take place in the client’s database and for others in the System A database.
So far, I’ve thought of a possible solution to this problem:
Upon receiving the request from the client on the System A web service, we verify that the client who makes the request has integration with this specific function. This, I imagined, could be done by making a query in the database, where each functionality would have its unique code next to the client’s code. It would be enough to inform the client code and the functionality code to know if it has integration for it. However, this does not solve the whole problem, since within the same functionality there may be methods that have integration or not. Therefore, each method of a feature would also need to have a unique code in the database. With this, in each request we would pass the unique code of this method along with the client code to know if the client has integration for this method. Assuming this previous part works, the next step would be, if the client had integration, how would we bypass their web service instead of our DAO? To solve this, I thought to add another level in the architecture of the web service of System A. Thus getting the flow of a request that had integration within the web service:
Resource Service Router DAO
The new layer, Routers, would exist only for functions that have some kind of integration with any client. It would be responsible for verifying if the client has integration for that specific method, if it has it, it would pass on to another class the demand to carry out this request in the client’s web service. If not, it will just call System A’s DAO method.
In this way, the Router class will have a reference to the DAO of System A, which was previously in the Service and also a reference to some kind of Requestdispatcher in order to pass to this class the demand to give continuity to a request that has integration.
In this approach, two things sound very strange to me and I still haven’t accepted them very well:
The fact that each Resource method has to have a unique code to be able to link, in the database, to the client that has integration. This seems very subject to errors and difficult to manage the more the software grows.
If the Router discovers that the client has an integration in that particular method, how will it know which Requestdispatcher to instantiate? Each customer should have their own. For each integrated functionality. This creation can be demanded for a Factory, however, would this Factory have to have the code of the hardcoded clients in order to instantiate the correct Dispatcher? Sounds like code Smell to me.
As I said, this possible solution did not convince me by the cons that it adds, so I would like ideas and suggestions. Who knows who has ever had experience with it can tell us the least turbulent way forward.
Thank you!
Hello, Bruno. Your alternative to the flow is also correct. However, there are moments that I will access only the DAO, others the WS (ERP). Who knows in some cases even both. I understand your argument, and I agree that there is no alternative but to create unique identifiers for each method, right? However, in the
RequestDispatcher
I would also need to have the unique code of each hardcoded client, to be able to instantiate the correct object, or not? I don’t have much to escape from making that communication with every specific ERP. Even being more expensive, that’s what customers want.– Luiz
@Luiz The identifiers are not for the methods but for the objects that will be stored in the database. I do not know. You’ll have to give details of the various Erps to get a better idea of the situation. If all Erps obey the rules I said Windows can do only 1 module and have a folder for each ERP. These folders will only have one or more configuration files.
– Bruno Costa
@Luiz Editei the answer.
– Bruno Costa
Good answer! However, I believe that it is not very scalable. An interface to define all operations would soon become something too big. Another point is that for me to use the
IntegradorBaseDeDados
, It would be necessary for my Daos to implement, probably, Ioperacoes, if I understood what you meant. Actually, it wasn’t very clear to me where the Daos would fit into this model. I cannot fit this solution with the large number of Daos that exist in the project.– Luiz
@Luiz the number of operations however large is ephemeral. No, your Daos do not have to implement Ioperacoes. But you would receive an implementation of them in your database integrator. Depending on the operation you want to do you can use an arbitrary number of operations of your Daos
– Bruno Costa
Although I didn’t specifically meet my needs, I relied on your UML to create and implement the version we are using. I appreciate the dedication in helping, it was very helpful. More than deserved the reward. Thank you! ;)
– Luiz