What is the big idea behind the AOP implementation - java

I wanted to make it clear for me.
I read about AOP concept and I understood that it's a great way to share cross cutting services. (logging, security, transaction...)
But I would like to say/ask something about this idea and it's implementation.
I read there are some ways like AspectJ, JBOSS AOP in order to assimilation AOP to my business logic.
but wasnt it here already long time ago?
let's say for example I want to share a logging or security implementation amongs my components(Java beans, EJB'S, whatsoever.. )
Why couldn't I make a Singleton bean making sure it will has only one instance and as soon as any component will need it's logging/security service it would look-up and use it's service.
Why would I need to understand and have all those "Big" implementations such as aspectj or jboss AOP? What do I miss here?

The idea of AOP is to keep common logic in one place (which your singleton solution solves as well) and being "invisible" (transparent). With AOP your logging code isn't even part of the business logic, it is "injected" behind the scenes.
Also it is more dynamic - you don't need to call your singleton service every time you need logging. Just configure a pointcut once (like: "all setters in this package") and logging will be applied for all existing and new code.
Moreover AOP is much, much more flexible and powerful. You can ask the AOP implementation: "please start a transaction every time I call a method beginning with "save*" and taking one argument" or "if method returning Customer throws an exception subclassing from IllegalAgumentException, call that method again".
AOP is much more than just grouping common logic.

You have not understood what AOP is all about. The idea of AOP is to be able to write
public void foo() {
// some business code
}
instead of writing
public void foo() {
LogManager.getInstance().log("entering foo...");
SecurityManager.getInstance().checkUserInRole("fooer");
TransactionManager.getInstance().startTransaction();
try {
// some business code
TransactionManager.getInstance().commit();
}
catch(RuntimeException e) {
TransactionManager.getInstance().rollback();
throw e;
}
LogManager.getInstance().log("leaving foo...");
}
All the cross-cutting concerns (logging, security, transaction management) are outside of the business code, instead of being mixed with the business code, and repeated ad nauseam.

Related

Reusing same #Transactional method for different DataSources (JdbcTemplate) in Spring

we have this code where the same service method will call different daos each using a different datasource (and different JdbcTemplates). We would like to use #Transactional annotation, but as far as I know, this annotation is always linked to a specific TransactionManager (and thus, to a specific DataSource).
So, my question is, is there a way to choose dynamically which DataSource (or TransactionManager) using when calling a #Transactional method so I can reuse that method to attack different databases?
The #Transactional annotation doesn't allow dynamic evaluation of the value attribute which selects the TransactionManager (possibly by design, at least it doesn't look like it's going to change any time soon). So you can't have something like #Transactional("#{#getTxManager}") which would resolve the tx manager at call time.
In simple cases you might be able to get away with the following, but it would only be worth considering when for example you have a primary DS, and a secondary DS that's used only in some cases. Otherwise you'd be peppering the code that selects between calling foo/bar all around, and that wouldn't look clean at all
// TX boundary on the "top" abstraction layer
#Transactional("foo")
public void foo() {
doWork();
}
#Transactional("bar")
public void bar() {
doWork();
}
private void doWork() {
// Work done here, no concern for tx management
}
For more complex cases like multitenancy, AbstractRoutingDataSource is an easy and robust choice if you haven't considered it yet. Although depending on how much switching you need, it may require tweaking or be even unsuitable.
Finally, you might be able to create your own annotation that does choose the DS dynamically (although I don't guarantee it), but that would be the riskiest approach for possible very little gains.
The safest way for you would be to create separate services for each dao... I wouldn't like to be debugging such code. Think about maintaining this code and possible failures that might happen.
If I were you I'd ask myself following questions:
1.) Why separate dbs?
2.) Isn't the context somehow mixed up? Maybe create some boundaries between them?
3.) Do my queries really need to be transactional?
I probably don't know the context of your problem but for me it seems that you've modeled your application in a wrong way and I'd focus on it.

Why is Spring's ApplicationContext.getBean with Interface considered bad? [duplicate]

I asked a general Spring question: Auto-cast Spring Beans and had multiple people respond that calling Spring's ApplicationContext.getBean() should be avoided as much as possible. Why is that?
How else should I gain access to the beans I configured Spring to create?
I'm using Spring in a non-web application and had planned on accessing a shared ApplicationContext object as described by LiorH.
Amendment
I accept the answer below, but here's an alternate take by Martin Fowler who discusses the merits of Dependency Injection vs. using a Service Locator (which is essentially the same as calling a wrapped ApplicationContext.getBean()).
In part, Fowler states, "With service locator the application class asks for it [the service] explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.
Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it [Inversion of Control] unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative."
I mentioned this in a comment on the other question, but the whole idea of Inversion of Control is to have none of your classes know or care how they get the objects they depend on. This makes it easy to change what type of implementation of a given dependency you use at any time. It also makes the classes easy to test, as you can provide mock implementations of dependencies. Finally, it makes the classes simpler and more focused on their core responsibility.
Calling ApplicationContext.getBean() is not Inversion of Control! While it's still easy to change what implemenation is configured for the given bean name, the class now relies directly on Spring to provide that dependency and can't get it any other way. You can't just make your own mock implementation in a test class and pass that to it yourself. This basically defeats Spring's purpose as a dependency injection container.
Everywhere you want to say:
MyClass myClass = applicationContext.getBean("myClass");
you should instead, for example, declare a method:
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
And then in your configuration:
<bean id="myClass" class="MyClass">...</bean>
<bean id="myOtherClass" class="MyOtherClass">
<property name="myClass" ref="myClass"/>
</bean>
Spring will then automatically inject myClass into myOtherClass.
Declare everything in this way, and at the root of it all have something like:
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication is the most central class, and depends at least indirectly on every other service in your program. When bootstrapping, in your main method, you can call applicationContext.getBean("myApplication") but you should not need to call getBean() anywhere else!
Reasons to prefer Service Locator over Inversion of Control (IoC) are:
Service Locator is much, much easier for other people to following in your code. IoC is 'magic' but maintenance programmers must understand your convoluted Spring configurations and all the myriad of locations to figure out how you wired your objects.
IoC is terrible for debugging configuration problems. In certain classes of applications the application will not start when misconfigured and you may not get a chance to step through what is going on with a debugger.
IoC is primarily XML based (Annotations improve things but there is still a lot of XML out there). That means developers can't work on your program unless they know all the magic tags defined by Spring. It is not good enough to know Java anymore. This hinders less experience programmers (ie. it is actually poor design to use a more complicated solution when a simpler solution, such as Service Locator, will fulfill the same requirements). Plus, support for diagnosing XML problems is far weaker than support for Java problems.
Dependency injection is more suited to larger programs. Most of the time the additional complexity is not worth it.
Often Spring is used in case you "might want to change the implementation later". There are other ways of achieving this without the complexity of Spring IoC.
For web applications (Java EE WARs) the Spring context is effectively bound at compile time (unless you want operators to grub around the context in the exploded war). You can make Spring use property files, but with servlets property files will need to be at a pre-determined location, which means you can't deploy multiple servlets of the same time on the same box. You can use Spring with JNDI to change properties at servlet startup time, but if you are using JNDI for administrator-modifiable parameters the need for Spring itself lessens (since JNDI is effectively a Service Locator).
With Spring you can lose program Control if Spring is dispatching to your methods. This is convenient and works for many types of applications, but not all. You may need to control program flow when you need to create tasks (threads etc) during initialization or need modifiable resources that Spring didn't know about when the content was bound to your WAR.
Spring is very good for transaction management and has some advantages. It is just that IoC can be over-engineering in many situations and introduce unwarranted complexity for maintainers. Do not automatically use IoC without thinking of ways of not using it first.
It's true that including the class in application-context.xml avoids the need to use getBean. However, even that is actually unnecessary. If you are writing a standalone application and you DON'T want to include your driver class in application-context.xml, you can use the following code to have Spring autowire the driver's dependencies:
public class AutowireThisDriver {
private MySpringBean mySpringBean;
public static void main(String[] args) {
AutowireThisDriver atd = new AutowireThisDriver(); //get instance
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"/WEB-INF/applicationContext.xml"); //get Spring context
//the magic: auto-wire the instance with all its dependencies:
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
// code that uses mySpringBean ...
mySpringBean.doStuff() // no need to instantiate - thanks to Spring
}
public void setMySpringBean(MySpringBean bean) {
this.mySpringBean = bean;
}
}
I've needed to do this a couple of times when I have some sort of standalone class that needs to use some aspect of my app (eg for testing) but I don't want to include it in application-context because it is not actually part of the app. Note also that this avoids the need to look up the bean using a String name, which I've always thought was ugly.
One of the coolest benefits of using something like Spring is that you don't have to wire your objects together. Zeus's head splits open and your classes appear, fully formed with all of their dependencies created and wired-in, as needed. It's magical and fantastic.
The more you say ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed");, the less magic you're getting. Less code is almost always better. If your class really needed a ClassINeed bean, why didn't you just wire it in?
That said, something obviously needs to create the first object. There's nothing wrong with your main method acquiring a bean or two via getBean(), but you should avoid it because whenever you're using it, you're not really using all of the magic of Spring.
The motivation is to write code that doesn't depend explicitly on Spring. That way, if you choose to switch containers, you don't have to rewrite any code.
Think of the container as something is invisible to your code, magically providing for its needs, without being asked.
Dependency injection is a counterpoint to the "service locator" pattern. If you are going to lookup dependencies by name, you might as well get rid of the DI container and use something like JNDI.
Using #Autowired or ApplicationContext.getBean() is really the same thing. In both ways you get the bean that is configured in your context and in both ways your code depends on spring.
The only thing you should avoid is instantiating your ApplicationContext. Do this only once! In other words, a line like
ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");
should only be used once in your application.
One of Spring premises is avoid coupling. Define and use Interfaces, DI, AOP and avoid using ApplicationContext.getBean() :-)
One of the reasons is testability. Say you have this class:
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
#Component
class MyBean {
#Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
How can you test this bean? E.g. like this:
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
Easy, right?
While you still depend on Spring (due to the annotations) you can remove you dependency on spring without changing any code (only the annotation definitions) and the test developer does not need to know anything about how spring works (maybe he should anyway, but it allows to review and test the code separately from what spring does).
It is still possible to do the same when using the ApplicationContext. However then you need to mock ApplicationContext which is a huge interface. You either need a dummy implementation or you can use a mocking framework such as Mockito:
#Component
class MyBean {
#Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
This is quite a possibility, but I think most people would agree that the first option is more elegant and makes the test simpler.
The only option that is really a problem is this one:
#Component
class MyBean {
#Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
Testing this requires huge efforts or your bean is going to attempt to connect to stackoverflow on each test. And as soon as you have a network failure (or the admins at stackoverflow block you due to excessive access rate) you will have randomly failing tests.
So as a conclusion I would not say that using the ApplicationContext directly is automatically wrong and should be avoided at all costs. However if there are better options (and there are in most cases), then use the better options.
The idea is that you rely on dependency injection (inversion of control, or IoC). That is, your components are configured with the components they need. These dependencies are injected (via the constructor or setters) - you don't get then yourself.
ApplicationContext.getBean() requires you to name a bean explicitly within your component. Instead, by using IoC, your configuration can determine what component will be used.
This allows you to rewire your application with different component implementations easily, or configure objects for testing in a straightforward fashion by providing mocked variants (e.g. a mocked DAO so you don't hit a database during testing)
Others have pointed to the general problem (and are valid answers), but I'll just offer one additional comment: it's not that you should NEVER do it, but rather that do it as little as possible.
Usually this means that it is done exactly once: during bootstrapping. And then it's just to access the "root" bean, through which other dependencies can be resolved. This can be reusable code, like base servlet (if developing web apps).
There is another time when using getBean makes sense. If you're reconfiguring a system that already exists, where the dependencies are not explicitly called out in spring context files. You can start the process by putting in calls to getBean, so that you don't have to wire it all up at once. This way you can slowly build up your spring configuration putting each piece in place over time and getting the bits lined up properly. The calls to getBean will eventually be replaced, but as you understand the structure of the code, or lack there of, you can start the process of wiring more and more beans and using fewer and fewer calls to getBean.
I've only found two situations where getBean() was required:
Others have mentioned using getBean() in main() to fetch the "main" bean for a standalone program.
Another use I have made of getBean() are in situations where an interactive user configuration determines the bean makeup for a particular situation. So that, for instance, part of the boot system loops through a database table using getBean() with a scope='prototype' bean definition and then setting additional properties. Presumably, there is a UI that adjusts the database table that would be friendlier than attempting to (re)write the application context XML.
however, there are still cases where you need the service locator pattern.
for example, i have a controller bean, this controller might have some default service beans, which can be dependency injected by configuration.
while there could also be many additional or new services this controller can invoke now or later, which then need the service locator to retrieve the service beans.
You should to use: ConfigurableApplicationContext instead of for ApplicationContext

Can someone exlpain advantage spring-security PreAuthorize annotations?

For example:
#PreAuthorize("hasRole('admin') && hasPermission('save', #user)")
void updateUser(User user) {
// some code
}
And some example implementation without PreAuthorize.
void updateUser(User user) {
Security.hasRole(Roles.ADMIN);
Security.hasPermission(Permission.SAVE, user);
// some code
}
The second example is more easy to understand. Can be refactored by IDE (rename role, or find all role usages). Code check at compile time. Work more fast. And may other advantages.
Why spring-security developers chose annotations and SpEL? Can some-one explain it?
Only one reason what i can find - more easy access to ApplicationContext. But as far as i can see, spring security any way work through SecurityContextHolder singleton.
The most advantage (from my point of view) is, that it can be easily deactivated (or more correct, not activated) in test.
So I can write my tests (unit test, functional test, ...) without paying any attention to the security stuff. So that the tests can concentrate on the function they want to test.
Of course this is also possible with the "explicit" version (second example), but then I need to take care about it in the test, that would make the tests longer (more code) and also means more stuff to maintain.
In addition to #Ralph answer I would add a couple of other advantages.
#PreAuthorize (& co.) are meta-annotated with #Documented, this means that the annotation will be shown in the Javadocs of the secured method. A reader of your documentation will know immediately that the method is secured and under what conditions.
Since it is meta-annotated with #Inherited, you can add the #PreAuthorize to a parent Class, and automatically have all the hierarchy to be secured without implementing any additional pattern.

Executing code before and after #Transactional method

We have a Spring based application with a service layer which is annotated with #Transactional. We need to have code run before and after some transactional methods for the following reasons:
We need to synchronize access to the method based on a key. The thread needs to block before the start of the transaction.
We need to post a message on a queue if the transaction succeeds.
The options seem to be:
Create a class with similar methods to the service that can run the #Transactional method in a synchronized block and check for the return then post the message (would need a separate class due to AOP proxy problem). Services calling services, not nice, feels like a work-around.
Write an aspect to wrap around the #Transactional AOP which can do the synchronization and message posting. Might work but would rather avoid AOP.
Move the transaction down to the domain layer. Not desirable or possibly even feasible with the current implementation due to the way domain methods are reused in different workflows.
Code the transaction by hand in the service method and scrap #Transactional.
I would imagine this is a fairly common requirement. Probably I am missing an option 5, which is the obvious one!
I think I'd go with 2 unless you have some specific reasons to avoid AOP. Your problem is a classic example of where AOP can be used and it looks pretty good in the result. Here is a nice example of how to implement that (if you didn't read that already): Advising transactional operations
If AOP is really not an option, I'd go the 'Otherwise' option proposed by #Lawrence McAlpin.
Check out TransactionSynchronization callback interface. Spring can natively inform you what is happening with your transaction.
I would use a TransactionTemplate (your option 4) and programatically control the scope of the transaction in situations like this.
Otherwise, you could move the logic in your method out into a separate service, make that new service #Transactional, remove the #Transactional from the current method, and then surround the call to the new service with your pre- and post-transaction logic. I've taken this approach as well, but I prefer programmatic transaction management for requirements like this, as I think it's cleaner and, as you mentioned, services calling services (that are only ever needed by the first service) just feels like a hackish workaround.
if the key is being passed as part of the method call, then you can use java ReentrantLock to do the job.. its much simpler & cleaner.

AOP: basic ideas - keep objects simple?

I work with Spring Framework 3.0.5 and Id like to understand the basic principals of Spring. One of it is AOP.
One basic idea of the spring framework is to keep the objects itself simple and to have clear code.
DI follows this basic idea. It provides clear code and the objects itself can be very simple. The dont have to look up their dependencys.
Now what about AOP: I mean, code is for sure clearer with AOP, but does AOP also have the basic idea of keeping the objects as simple as possible? Im not sure of that, thats why Id like to know some other opinions :-)
Thanks in advance!
The main motivation for AOP is to use it for so called cross-cutting concerns, as in functionality you need to provide in basically all parts of your application, usually these include:
logging
authentication
auditing
transactionality.
AOP allows you to extract these functionalities into separate classes and just mark your classes which need these.
Watch this excellent video to get the main idea. To answer your question, yes, it will help a lot to keep your classes clean, because they will only take care about their own functionality and don't have to provide boilerplate code over and over again.
Take the following code snippets as an example. The easy way:
#PersistenceContext
private EntityManager em;
#Transactional
public void save(Object obj) {
em.persist(obj);
}
The traditional way (you can manage transactions using EntityManager interface, but that is not the point):
#PersistenceContext
private EntityManager em;
#Resource
private AbstractPlatformTransactionManager transactionManager;
public void save(final Object obj) {
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status)
{
em.persist(obj);
}
});
}
What does it have to do with AOP? Transaction management is one of the most widely used examples of AOP and Spring is not an exception. The former code snippet uses #Transactional annotation to apply transaction demarcation using aspect, while the latter manages transactions manually. See the benefit?
The key thing: use aspects for cross-cutting concerns like logging, profiling, etc. Don't build your business logic in aspects. This way your beans remain clear while irrelevant code from business perspective is hidden in the aspect.
Also AOP allows you to do all sorts of sophisticated stuff with ease. Take for instance HTTP session handling - with session bean scope and AOP proxying you can access session without even realizing it.
To summarize - it is great tool when used for the right job.

Categories

Resources