I have some atomic operations in my code. From books that would be a class example.
You withdraw money from one user is the first database access. Then you put that money to another user, would be the second database access operation. Only both together can be executed. If the first succeeds and the second fails, the whole operation has to be rolled back.
So in my application I also have this. Maybe it will never happen but to be sure I made it a transaction.
For example. The user saves its holidays. And also the holiday itself is also saved in another table.
This is my code. I decided to put all transactions in this class. i called it transaction service.
I hope it's ok. I just was a little bit confused when I got an error message there would be 2 transaction manager in my application. I just decided to use the one called transactionManager.
#Service
public class TransactionService {
private UserDao userDao;
private HolidayDao holidayDao;
private WorkingMonthDao workingMonthDao;
#Autowired
public TransactionService(UserDao userDao,HolidayDao holidayDao,WorkingMonthDao workingMonthDao)
{
this.userDao = userDao;
this.holidayDao = holidayDao;
this.workingMonthDao = workingMonthDao;
}
//#Transactional(isolation=Isolation.READ_COMMITTED, propagation=Propagation.REQUIRED,readOnly=false,timeout=1000, rollbackFor=Exception.class)
#Transactional(value="transactionManager")
public void saveUserAndHoliday(User user, Holiday holiday)
{
userDao.save(user);
holidayDao.save(holiday);
}
#Transactional(value="transactionManager")
public void saveUserAndDeleteHoliday(User user, Holiday holiday)
{
holidayDao.delete(holiday);
userDao.save(user);
}
#Transactional(value="transactionManager")
public void saveUserAndWorkingMonth(User user, WorkingMonth workingMonth)
{
userDao.save(user);
workingMonthDao.save(workingMonth);
}
}
I would give another name to such a service, possibly splitting it into several classes based on business logic domain.
Supposing you are adhere to clean code principles and want to build low coupled application, that can be easily supported in the future.
Transactions are said to belong to cross-cutting concern of application architecture. That means that transaction related classes should not contain application core logic. Example of such classes could be custom transaction manager. All your methods saveUserAndHoliday, saveUserAndDeleteHoliday and saveUserAndWorkingMonth are responsible for part of a business logic, although small part - combining different DAOs. In my practice we used to call such classes as Repositories - intermediate layer between services (core business logic layer) and DAOs (persistance layer).
Related
Our application calls many external API's which take a session token of the current user as input. So what we currently do is in a controller, get the session token for the user and pass it into a service which in turn might call another service or some API client. To give an idea, we end up with something like this (example is .NET but something similar is I think possible in Java)
public IActionResult DoSomething(string something)
{
this.someService.DoSomethingForUser(this.HttpContext.SessionToken, something);
return View();
}
And then we have
public class SomeService
{
private readonly IApiClient apiClient;
public SomeService(IApiClient apiClient)
{
this.apiClient = apiClient;
}
public void DoSomethingForUser(string sessionToken, something)
{
this.apiClient.DoSomethingForUser(sessionToken, something);
}
}
It can also happen that in SomeService another service is injected which in turn calls the IApiClient instead of SomeService calling IApiClient directly, basically adding another "layer".
We had a discussion with the team if it isn't better to instead of passing the session token, inject it using DI so you get something like this:
public IActionResult DoSomething(string something)
{
this.someService.DoSomethingForUser(something);
return View();
}
And then we have
public class SomeService
{
private readonly IUserService userService;
private readonly IApiClient apiClient;
public SomeService(IUserService userService, IApiClient apiClient)
{
this.userService = userService;
this.apiClient = apiClient;
}
public void DoSomethingForUser(string something)
{
this.apiClient.DoSomethingForUser(userService.SessionToken, something);
}
}
The IUserService would have an IHttpContextAccessor injected:
public class UserService : IUserService
{
private readonly IHttpContextAccessor httpContextAccessor;
public UserService(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public string SessionToken => httpContextAccessor.HttpContext.SessionToken;
}
The benefits of this pattern are I think pretty clear. Especially with many services, it keeps the code "cleaner" and you end up with less boilerplate code to pass a token around.
Still, I don't like it. To me the downsides of this pattern are more important than its benefit:
I like that passing the token in the methods is concise. It is clear that the service needs some sort of authentication token for it to function. I'm not sure if you can call it a side effect but the fact that a session token is magically injected three layers deep is impossible to tell just by reading the code
Unit testing is a bit more tedious if you have to Mock the IUserService
You run into problems when calling this in another thread, e.g. calling SomeService from another thread. Although these problems can be mitigated by injecting another concrete type of IUserService which gets the token from some place else, it feels like a chore.
To me it strongly feels like an anti pattern but apart from the arguments above it is mostly a feeling. There was a lot of discussion and not everybody was convinced that it was a bad idea. Therefor, my question is, is it an anti pattern or is it perfectly valid? What are some strong arguments for and against it, hopefully so there can be not much debate that this pattern is indeed, either perfectly valid or something to avoid.
I would say the main point is to enable your desired separation of concerns. I think it is a good question if expressed in those terms. As Kit says, different people may prefer different solutions.
REQUEST SCOPED OBJECTS
These occur quite naturally in APIs. Consider the following example, where a UI calls an Orders API, then the Orders API forwards the JWT to an upstream Billing API. A unique Request ID is also sent, in case the flow experiences a temporary problem. If the flow is retried, the Request ID can be used by APIs to prevent data duplication. Yet business logic should not need to know about either the Request ID or the JWT.
BUSINESS LOGIC CLASS DESIGN
I would start by designing my logic classes with my desired inputs, then work out the DI later. In my example the OrderService class might use claims to get the user identity and also for authorization. But I would not want it to know about HTTP level concerns:
public class OrderService
{
private readonly IBillingApiClient billingClient;
public OrderService(IBillingApiClient billingClient, ClaimsPrincipal user)
{
this.billingClient = billingClient;
}
public async void CreateOrder(OrderInput data)
{
this.Authorize();
var order = this.CreateOrder(data);
await this.billingClient.CreateInvoice(order);
}
}
DI SETUP
To enable my preferred business logic, I would write a little DI plumbing, so that I could inject request scoped dependencies in my preferred way. First, when the app starts, I would create a small middleware class. This will run early in the HTTP request pipeline:
private void ConfigureApiMiddleware(IApplicationBuilder api)
{
api.UseMiddleware<ClientContextMiddleware>();
}
In the middleware class I would then create a ClientContext object from runtime data. The OrderService class will run later, after next() is called:
public class ClientContextMiddleware
{
public async Task Invoke(HttpContext context)
{
var jwt = readJwt(context.Request);
var requestId = readRequestId(context.Request);
var holder = context.RequestServices.GetService<ClientContextHolder>();
holder.ClientContext = new ClientContext(jwt, requestIO);
await this.next(context);
}
}
In my DI composition at application startup I would express that the API client should be created when it is first referenced. In the HTTP request pipeline, the OrderService request scoped object will be constructed after the middleware has run. The below lambda will then be invoked:
private void RegisterDependencies(IServiceCollection services)
{
this.services.AddScoped<IApiClient>(
ctx =>
{
var holder = ctx.GetService<ClientContextHolder>();
return new ApiClient(holder.context);
});
this.services.AddScoped<ClientContextHolder>();
}
The holder object is just due to a technology limitation. The MS stack does not allow you to create new request scoped injectable objects at runtime, so you have to update an existing one. In a previous .NET tech stack, the concept of child container per request was made available to developers, so the holder object was not needed.
ASYNC AWAIT
Request scoped objects are stored against the HTTP request object, which is the correct behaviour when using async await. The current thread ID may switch, eg from 4 to 6 after the call to the Billing API.
If the OrderService class has a transient scope, it could get recreated when the flow resumes on thread 6. If this is the case, then resolution will continue to work.
SUMMARY
Designing inputs first, then writing some support code if needed is a good approach I think, and it is also useful to know the DI techniques. Personally I think natural request scoped objects that need to be created at runtime should be usable in DI. Some people may prefer a different approach though.
See in dotnet the area that I am an expert is not an anti standard on the contrary it is the model that many adopt but it is not a model that I would follow for the following reasons
it is not clear where is the token for those who read and use it being an anti clean code
you load important information in a place that is frequently accessed by the framework in the case of .netCore
your classes will reference a large property carrying a lot of unnecessary information when you could have created a more clean model that costs less memory and allocation time, I'm saying this because the HttpAcessor carries all the information relevant to your request
As I would take care of readability (clean code) and improve my performance
I would make a middleware or filter in my flow mvc where I would do the authentication part and create a class like:
public class TokenAuthenciationValues
{
public string TokenClient { get; set; }
public string TokenValue { get; set; }
}
Of course my method is an example but in my middleware I would implement it by loading its token values after calling the necessary apis (of course this model needs an interface and it needs to be configured as .AddScoped() in the case of .net)
That way I would use it in my methods only instantiating my ITokenAuthenciationValues in the constructor and I would have clear and clean information loaded in memory during the entire request
If it is necessary in the middle of the request to change the token any class can access it and change its value
I would have less memory allocated unused in my classes since the IHttpAcessor contract the ITokenAuthenciationValues only has relevant information
Hope this helps
In most of Java cases there exist two classes: one responsible for apply my business rules - Service layer - and another one responsible for interacting with my database - Dao/Repository layer. However, in PHP cases I just have one class that represents model Layer. My question is, assuming Laravel Framework, should I put my business rules inside a unique model class or there is another approach similar with JSF for instance? Can I use a Middleware class as a Service layer?
To be honest you can use Service/Repo Layers in PHP as well.
So what happens is
Controller passes the inputs to the service and service decides what action is to be done.
The Service Layer then calls the repo for receiving entries from database wherever necessary and perform all the business logic.
The Repo calls the model and data from the model is returned.
The Model only keeps Model specific data (like relations, appended attributes, casts array etc etc...)
To follow this approach, something like this can be done.
Controller
use App\Services\PostService;
class PostController
{
public function __construct()
{
$this->postService = new PostService;
}
public function show($id)
{
$viewData = $this->postService->getPostData($id);
return view('posts.show', $viewData);
}
}
Service Layer
use App\Repositories\PostRepository;
use App\Repositories\CommentRepository;
class PostService
{
public function __construct()
{
$this->postRepo = new PostRepository;
$this->commentRepo = new CommentRepository;
}
public function getPostData($id)
{
$post = $this->postRepo->get($id);
$recentComments = $this->commentsRepo->getRecentComments();
return collect(compact('post', 'recentComments'));
}
}
Repository Layer
use App\Models\Post;
public function PostRepository
{
public function get()
{
return Post::findOrFail($id);
}
}
Also, for your last question, I'd like to say, Middlewares are meant to be used as a per-requisite only. In other words, lets say you want to ensure a user is logged in to view that particular route, then you'll apply the auth middleware and protect your routes from other not-logged in users... According to me, using Service Layer as Middleware isn't really required. You can obviously call a service layer in a Middleware by $this->myService = new Service but making it as a middleware doesn't really sound a good practice.
Hope I answered your question well enough :)
I have a problem with establishing a transaction manager/scope for my REST API (JAVA), I have below functions in my API back end and i want to excute all below functions as one transaction,
Call third party WS end point
Decrypt the response
Save the response in to DB1
Save the response in to DB2
I want to make sure all above steps are completed or rollback if any one fail, I have enough information to do the rollback, but i have no idea what would be the best practice to implement proper transaction management mechanism, because above mentioned steps happen in 3 separate classes per API call,
This is a pseudo code for my class structure
class CallWS {
public People callThWS() {
// functions related to call third party WS and decryption (step 1,2)
}
}
class People peopleServices {
public People getPeopleData() {
callThWS ppl= new callThWS();
People pplObj = ppl.callThWS();
// save to DB1, (step 3)
return pplObj;
}
}
class People peopleContr {
public People getAllPeople() {
peopleServices ppSer= new peopleServices();
People pplObj2 = ppSer.getPeopleData();
// save to DB2, (Step 4)
return pplObj2;
}
}
Please help me on this,
Thanks
What you need is Distributed Transactions(XA). Check for examples of various transaction managers which support XA. Check this article for using XA provider in standalone applications(Warning: Old article).
If you control sources of all classes listed and you can refactor your code the way you have a single entry point, you can do it quite easily, except the call to an external web service. The pseudo code is below.
Here we should agree that all resources your are calling in your methods are transactional. As I mentioned earlier call to an external WS would not fall to that category because calls to external web services are not transactional by their nature. Again if you do not change data withing a call to the external service you may consider just leave it outside transaction. You still have a bit of control. Like rolling back transaction in case a call to the external service was unsuccessful and as far as you have not changed anything on the other side, you may not care about rolling back a transaction there.
However you still have some options for a transaction call to an external WS call like Web Services Atomic Transactions, but I bet you would need control for sources and maybe even environment on the other side. In such a lucky circumstances you would rather want to achieve it by avoiding the WS call.
class RestAPIEntryPointResource {
#Inject
CallWS callWS;
#Inject
PeopleServices peopleServices ;
#Inject
PeopleContr peopleContr;
/*Put some transaction demarcation here.
If your class is an EJB, it is already done for you.
With Spring you have various options to mark the method transactional.
You also may want to take a manual control, but it look redundant here. */
public void entryPointMethod() {
callWS.callThWS();
peopleServices.getPeopleData();
peopleContr.getAllPeople();
}
}
class CallWS {
public People callThWS() {
// functions related to call third party WS and decryption (step 1,2)
}
}
class PeopleServices {
public People getPeopleData() {
..........
}
}
class PeopleContr {
public People getAllPeople() {
.........
}
}
I want to create an app following the DDD approach using Spring. Supose that I have a business model class Foo and an interface FooRepository.
DDD tells that the implementation of FooRepository should include in Infrastructure layer.
I would want to use CrudRepository but if I define in the domain layer:
public interface FooRepository extends CrudRepository<Foo, Long>{
// Some methods
}
I break with the core concept that the domain layer (FooRepository interface) must not know the infrastructure layer (CrudRepository).
I'm reading about this Domain Driven Design a few months ago but I haven't found a framework that supports it purely.
How I can do it the right way?
In the layered architecture you usually have 3 layers: application, domain and infrastructure.
Infrastructure
Here I put the implementation of the repository. In your case this is the implementation of CrudRepository which I would implement directly in concrete classes, without the use of an intermediate interface. We make no whatsoever assumption as to how the single object in the warehouse behave, we only put them there and retrieve them efficiently. This way we have no knowledge of the domain. We only offer the domain an interface to interact with: the set of public methods of WarehouseRepository.
public class WarehouseRepository implements CrudRepository<Foo, Long> {
...
}
Domain
Here various part of the model interact with the WarehouseRepository when you are inside a UnitOfWork/Transaction. In the method adjustQuantityPlus we se only domain logic which is not interesting to the application and need not to be known at infrastructure level.
public class SaleOrder {
public adjustQuantityPlus(LineItemID lineItemID,
WarehouseRepository warehouseRepository) {
this.lineItems.get(lineItemID).addOne(); //<-- add one to the order
Product product =
warehouseRepository.findByLineItem(lineItem);
product.minusOneFromStock(); //<-- decrease one from stock
}
}
Application
Here we start and stop transactions (UOWork) which manipulates many domain objects. Every business method correspond to a business use case.
public class CustomerEventsManager {
#Inject WarehouseRepository warehouseRepository;
#Inject SaleOrderRepository saleOrderRepository;
#Transactional
public wantsOneMoreOf(ProductID productID, SaleOrderID saleOrderID) {
SaleOrder saleOrder =
saleOrderRepository.findByID(saleOrderID)
saleOrder.adjustQuantityPlus(productToLineItem(productID),
warehouseRepository); //<-- add product
webPage.showPromoDiscount(); //<-- show promotional advertisement
}
}
The above code is a transaction, if the system couldn’t add the product to the order I don’t want to give the discount to the customer. The adjustQuantityPlus in turn is an inner “transaction” with domain logic, hidden to the application layer.
I have a couple of questions about Transactions in Spring if you may.
Let's suppose i have this DAO class :
public class MyDAO {
/**
* verifies if a certain record in DB contains 'True' in a certain Column named publishFlag
*/
#Transactional
public bloolean isBeingPublished(Long recordID){
...
}
/**
* sets the record's publishFlag column to true indicating that it's being published
*/
#Transactional
public boolean setBeingPublished(Long recordID){
...
}
}
And the following class using it :
public class MyClass {
#Autowired
MyDAO dao;
public void publishRecords(List<Long> ids){
for(Long id : ids){
if(!dao.isBeingPublished(id)){
dao.setBeingPublished(id);
//do something to publish the record
}
}
}
}
My questions are :
First of all, will the !dao.isBeingPublished(id) and dao.setBeingPublished(id) be executed in the same transaction or in separate ones?
Second question's about concurrency, Multiple MyClass instances can be created and concurrent calls to the publishRecord method can occur, so two concurrent calls to !dao.isBeingPublished(id) might both give the same result and thus making the record published twice!
I would consider making the publishRecords synchronized but the application may be deployed on multiple servers which renders the synchronized declaration useless, hence my question about transactions since the database is the only shared resource between the apps deployed on those servers.
What would be the solution to my problem exactly? I read about spring's transaction propagation and found out that REQUIRES_NEW would create a new transaction even if one is currently being executed, but still, I just can't see how that's going to be a solution to my problem.
Thank you in advance for your help.
Few things need consider, DAO is focus on operation on single entity, and service is focus on operation of one or more entities, so the transaction should put on service layer, so you can reuse DAO's operation without any transaction, but let service to decide when start and end transaction
It is not in single transaction, but two separate transaction.
That is the problem concurrency issue with your current design, see the following suggestion.
Interface
public interface MyClass {
public void publishRecords(List<Long> ids);
}
Implementation
#Service
#Transactional(readOnly = false)
class DefaultMyClass implements MyClass {
#Autowired
MyDAO dao;
// single transaction
#Override
public void publishRecords(List<Long> ids) {
for(Long id : ids){
if(!dao.isBeingPublished(id)){
dao.setBeingPublished(id);
//do something to publish the record
}
}
}
}
DAO
class MyDAO {
public bloolean isBeingPublished(Long recordID){
// bigbang
}
public boolean setBeingPublished(Long recordID){
// bigbang
}
}
Using the above design, both problems are being resolved.
First of all, will the !dao.isBeingPublished(id) and
dao.setBeingPublished(id) be executed in the same transaction or in
seperate ones?
Unless there's a method annotated with #Transactional further up the stack, they will be occurring in separate transactions, so yes you will have a potential for a race condition.
If I were you, I would toss the isBeingPublished and setBeingPublished in favor of a single #Transactional publishIfPossible method that returns a boolean value of whether it was able to acquire the database row lock and do the publish operation.