The following comments refer to the design employed in the large (370 persistent classes in the domain layer, thousands of presentation layer classes, ...) web app I am currently involved with.
And using a bloated base class has a lot of shortcomings which have been documented several times :
-You can't choose wich service you want.
Not sure what you mean, but the BaseAction class could certainly be programmed and/or configured to choose the appropriate transaction service.
-You have to deal with an overcomplex API in most cases.
Not in our case. The BaseAction class is the only client for the transaction demarcation service, in almost all use cases. Typical application (domain + UI) classes contain no such code.
-You have to explicity call methods (for instance to define transaction boundaries).
As already pointed out in the previous item, the code that deals with the transaction service is centralized in BaseAction. It is not spread in the codebase, as you seem to imply.
-Sometimes the concrete class is already extending another class.
Not in our case, and we have to extend from the Struts Action class anyway.
-Good luck reusing your code.
Our application infrastructure layer (including the BaseAction class) is, at least in principle, fully reusable for web apps following the same architecture, even though such reuse in other apps is not a project requirement.
-Your base class become severly bloated or depend upon a tons of other classes and become very fragile.
Granted, our BaseAction class could be simplified, but still, it only contains about 400 lines of code, and depends on five other infrastructure packages, only one of which are involved in transaction demarcation.
I hate the pull method, the push is way more powerful because :
-You don't need to call the service locator or whatever factories.
Yes, but with DI you need extra fields and setters/constructors, which are not needed with a ServiceLocator. So, in both cases there is additional complexity.
-You don't need to program tons of factories, builders,service locators, ...
An application usually needs no more than one ServiceLocator. For example, XyzService xyz = ServiceLocator.get(XyzService.class);.
Anyway, I'll stop here because this subject is already covered extensively but DI hasn't become so popular for nothing.
I have read lots on DI and Spring, but still am not convinced it's as useful as advertised. Maybe people just want to have more frameworks listed in their resume, I don't know.