As you many know when you proxy an object, like when you create a bean with transactional attributes for Spring/EJB or even when you create a partial mock with some frameworks, the proxies object doesn't know that, and internal calls are not redirected, and then not intercepted either...
That's why if you do something like that in Spring:
#Transactionnal
public void doSomething() {
doSomethingInNewTransaction();
doSomethingInNewTransaction();
doSomethingInNewTransaction();
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomethingInNewTransaction() {
...
}
When you call doSomething, you expect to have 3 new transactions in addition to the main one, but actually, due to this problem you only get one...
So i wonder how do you do to handle these kind of problems...
I'm actually in a situation where i must handle a complex transactional system, and i don't see any better way than splitting my service into many small services, so that I'm sure to pass through all the proxies...
That bothers me a lot because all the code belongs to the same functional domain and should not be split...
I've found this related question with interesting answers:
Spring - #Transactional - What happens in background?
Rob H says that we can inject the spring proxy inside the service, and call proxy.doSomethingInNewTransaction(); instead.
It's quite easy to do and it works, but i don't really like it...
Yunfeng Hou says this:
So I write my own version of CglibSubclassingInstantiationStrategy and
proxy creator so that it will use CGLIB to generate a real subclass
which delegates call to its super rather than another instance, which
Spring is doing now. So I can freely annotate on any methods(as long
as it is not private), and from wherever I call these methods, they
will be taken care of. Well, I still have price to pay: 1. I must list
all annotations that I want to enable the new CGLIB sub class
creation. 2. I can not annotate on a final method since I am now
generating subclass, so a final method can not be intercepted.
What does he mean by "which spring is doing now"? Does this mean internal transactional calls are now intercepted?
What do you think is better?
Do you split your classes when you need some transactional granularity?
Or do you use some workaround like above? (please share it)
I'll talk about Spring and #Transactional but the advise applies for many other frameworks also.
This is an inherent problem with proxy based aspects. It is discussed in the spring documentation here:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies
There are a number of possible solutions.
Refactor your classes to avoid the self-invocation calls that bypass the proxy.
The Spring documentation describes this as "The best approach (the term best is used loosely here)".
Advantages of this approach are its simplicity and that there are no ties to any framework. However, it may not be appropriate for a very transactional heavy code base as you'd end up with many trivially small classes.
Internally in the class get a reference to the proxy.
This can be done by injecting the proxy or with hard coded " AopContext.currentProxy()" call (see Spring docs above.).
This method allows you to avoid splitting the classes but in many ways negates the advantages of using the transactional annotation. My personal opinion is that this is one of those things that is a little ugly but the ugliness is self contained and might be the pragmatic approach if lots of transactions are used.
Switch to using AspectJ
As AspectJ does not use proxies then self-invocation is not a problem
This is a very clean method though - it is at the expense of introducing another framework. I've worked on a large project where AspectJ was introduced for this very reason.
Don't use #Transactional at all
Refactor your code to use manual transaction demarcation - possibly using the decorator pattern.
An option - but one that requires moderate refactoring, introducing additional framework ties and increased complexity - so probably not a preferred option
My Advice
Usually splitting up the code is the best answer and can also be good thing for seperation of concerns also. However, if I had a framework/application that heavily relied on nested transactions I would consider using AspectJ to allow self-invocation.
As always when modelling and designing complex use cases - focus on understandable and maintainable design and code. If you prefer a certain pattern or design but it clashes with the underlying framework, consider if it's worth a complex workaround to shoehorn your design into the framework, or if you should compromise and conform your design to the framework where necessary. Don't fight the framework unless you absolutely have to.
My advice - if you can accomplish your goal with such an easy compromise as to split out into a few extra service classes - do it. It sounds a lot cheaper in terms of time, testing and agony than the alternative. And it sure sounds a lot easier to maintain and less of a headache for the next guy to take over.
I usually make it simple, so I split the code into two objects.
The alternative is to demarcate the new transaction yourself, if you need to keep everything in the same file, using a TransactionTemplate. A few more lines of code, but not more than defining a new bean. And it sometimes makes the point more obvious.
Related
I'm fairly new to Java and joining a project that leverages the DDD pattern (supposedly). I come from a strong python background and am fairly anal about unit test driven design. That said, one of the challenges of moving to Java is the testability of Service layers.
Our REST-like project stack is laid out as follows:
ServiceHandlers which handles request/response, etc and calls specific implementations of IService (eg. DocumentService)
DocumentService - handles auditing, permission checking, etc with methods such as makeOwner(session, user, doc)
Currently, something like DocumentService has repository dependencies injected via guice. In a public method like DocumentService.makeOwner, we want to ensure the session user is an admin as well as check if the target user is already an owner (leveraging the injected repositories). This results in some dupe code - one for both users involved to resolve the user and ensure membership, permissions, etc etc. To eliminate this redundant code, I want make a sort of super simpleisOwner(user, doc) call that I can concisely mock out for various test scenarios (such as throwing the exception when the user can't be resolved, etc). Here is where my googling fails me.
If I put this in the same class as DocumentService, I can't mock it while testing makeOwner in the same class (due to Mockito limitations) even though it somewhat feels like it should go here (option1).
If I put it in a lower class like DocumentHelpers, it feels slightly funny but I can easily mock it out. Also, DocumentHelpers needs the injected repository as well, which is fine with guice. (option 2)
I should add that there are numerous spots of this nature in our infant code base that are untestable currently because methods are non-statically calling helper-like methods in the same *Service class not used by the upper ServiceHandler class. However, at this stage, I can't tell if this is poor design or just fine.
So I ask more experienced Java developers:
Does introducing "Service Helpers" seem like a valid solution?
Is this counter to DDD principals?
If not, is there are more DDD-friendly naming convention for this aside from "Helpers"?
3 bits to add:
My googling has mostly come up with debates over "helpers" as static utility methods for stateless operations like date formatting, which doesn't fit my issue.
I don't want to use PowerMock since it breaks code coverage and is pretty ugly to use.
In python I'd probably call the "Service Helper" layer described above as internal_api, but that seems to have a different meaning in Java, especially since I need the classes to be public to unit test them.
Any guidance is appreciated.
That the user who initiates the action must be an admin looks like an application-level access control concern. DDD doesn't have much of an opinion about how you should do that. For testability and separation of concerns purposes, it might be a better idea to have some kind of separate non-static class than a method in the same service or a static helper though.
Checking that the future owner is already an owner (if I understand correctly) might be a different animal. It could be an invariant in your domain. If so, the preferred way is to rely on an Aggregate to enforce that rule. However, it's not clear from your description whether Document is an aggregate and if it or another aggregate contains the data needed to tell if a user is owner.
Alternatively, you could verify the rule at the Application layer level but it means that your domain model could go inconsistent if the state change is triggered by something else than that Application layer.
As I learn more about DDD, my question doesn't seem to be all that DDD related and more just about general hierarchy of the code structure and interactions of the layers. We ended up going with a separate DocumentServiceHelpers class that could be mocked out. This contains methods like isOwner that we can mock to return true or false as needed to test our DocumentService handling more easily. Thanks to everyone for playing along.
I am trying to have an annotation #FeatureDependent be used on methods to signal that the method requires certain things to be enabled in order for it to work. And I was wondering if it was possible to have a method called everytime a method with #FeatureDependent was called which would check if the criteria were met for the method to be called.
It sounds like you are describing Aspect Oriented Programming (AOI). This technique allows you to address "cross-cutting" concerns, tasks like logging, security, and transaction management which tend to affect many methods in the same manner. Your use case sounds like it would be a good fit for AOP.
There are two common approaches to AOP. The first mechanism is to create objects in a container (e.g. a Spring container). The container can then scan the class, detect any advice that needs to be applied, and apply the advice via dynamic proxies (Googling Spring and AOP is a good place to start with this). The downside is that your components will need to be constructed by a container so it makes sense for larger components.
The second approach is an extra compilation step (sometimes done at compilation, sometimes done as a separate compilation phase, and sometimes done by a weaving class loader) to wire in the additional methods. This is typically called "weaving" and AspectJ is a common library to look into for this.
Both approaches will allow you to apply "advice" (code run before and after a method invocation) based on annotations on an object. Explaining either in more detail would be beyond the scope of a SO answer but I hope it can get you started.
I should warn that AOP has gotten a bit of a reputation for complicating the flow of an application and tending to be difficult to understand and debug. As a result it has declined in popularity lately.
Another approach is to use something like Servlet Filters, basically a single choke point for all requests and workflows where you can apply various logging & security mechanisms. Such an approach tends to be a little easier to understand and involve a bit less "black magic".
We have a typical n-tier java application, and I noticed that our data access layers has DAO's that are of the type FooDAO and FooDAOImpl. I was looking to justify the need for the two and here is my analysis.
If you had multiple implementation for the same interface, the abstraction is helpful. But given that we have already made the choice of the framework to be used for the DAOImpl (say iBATIS), is it really required?
Help in proxying via Spring. From what I gather, classes that have interfaces can be proxied easily (going the JdkProxy route) rather than classes that have no interfaces (where the cglib route is chosen) and one has the subclass the class to be proxied. Subclassing has its problems where the class to proxied is final or has none default constructors - both of which are highly unlikely at the data access layer. Performance used to be a factor, but from what I hear, it is no longer a cause of concern.
Help in mocking. Classes with interfaces are more suited to be mocked by mocking frameworks. I have only heard this, but not seen it in practice - so can't really count on it, but maybe because of the same factors as mentioned in #2 above.
With these points, I don't feel the real need for a separate FooDAO and FooDAOImpl where a simple FooDAO should suffice. Feel free to correct any of the points that I have mentioned.
Thanks in advance!
I tried #3 with Mockito and it was able to mock POJO's without interfaces just fine. With the arguments mentioned against #1 and #2, I am inclined not to go with separate DAO and DAOImpl for now. Feel free to add other points of comparison.
I see a fourth reason:
Hide implementation details
Depending for instance on the team, the expected lifetime of the software or the amount of change anticipated in the future, it pays to hide as much as possible even if there is only one implementation.
I would say that having a FooDAO interface with a single implementation FooDAOImpl is generally an anti-pattern. The simpler solution (no separate interfaces for DAOs) is much preferable, unless you have a solid reason otherwise - which doesn't seem to be the case here.
Personally, I would go even further and say that having DAOs at all is not the best choice. I prefer having a single persistence facade class implemented on top of an ORM API such as Hibernate or JPA. Maybe iBATIS is too low-level for that, though.
I have tried to understand AOP, Dependency Injection and Inversion of Control SPRING related concepts but I am having hard time understanding it.
Can anyone explain this in simple English ?
I understand your confusion and it took me some time to understand how these concepts were related together. So here is my (somehow personal) explanation of all this:
1. Inversion of Control
Inversion of control is a design principle rather generic that refers to the decoupling of the specification of a behavior from when it is actually executed. Compare for instance,
myDependency.doThis();
with
myDependency.onEventX += doThis();
In the latter, there is no direct invocation which is more flexible. In its general form, inversion of control relates to the observer pattern, events, or callbacks.
2. Dependency inversion
Dependency inversion is another design principle. Roughly speaking, it says that higher-level abstraction should not depend directly on lower-level abstractions; this results indeed in a design where higher-level abstraction can not be reused without the lower-level abstractions.
class MyHighLevelClass {
MyLowLevelClass dep = new MyLowLeverClass();
}
class App {
void main() { new HighLevelClass().doStuff(); }
}
Here, MyHighLevelClass can not compile without access to MyLowLevelClass. To break this coupling, we need to abstract the low level class with an interface, and remove the direct instantiation.
class MyLowLevelClass implements MyUsefulAbstraction { ... }
class MyHighLevelClass {
MyUsefulAbstraction dep;
MyHighLevelClass( MyUsefulAbstraction dep ) {
this.dep = dep;
}
}
class App {
void main() { new HighLevelClass( new LowLevelClass() ).doStuff(); }
}
Note that you don't need anything special like a container to enforce dependency inversion, which is a principle. A good reading is The Dependency Inversion Principle by Uncle Bob.
3. Dependency injection
Now comes dependency injection. To me dependency injection = IoC + dependency inversion:
dependencies are provided externally so we enforce the dependency inversion principle
the container sets the dependencies (not us) so we speak of inversion of control
In the example I provided above, dependency injection can be done if a container is used to instantiate objects and automatically inject the dependency in the constructor (we speak then frequently of DI container):
class App {
void main() { DI.getHighLevelObject().doStuff(); }
}
Note that there are various form of injections. Note also that under this perspective, setter injection can be seen as a form of callback -- the DI container creates the object then calls back the setter. The flow of control is effectively inverted.
4. AOP
Strictly speaking, AOP has little to do with the 3 previous points. The seminal paper on AOP is very generic and present the idea of weaving various sources together (possibly expressed with different languages) to produce a working software.
I won't expand more on AOP. What is important here, is that dependency injection and AOP do effectively plays nicely together because it makes the weaving very easy. If an IoC container and dependency injection is used to abstract away the instantiation of objects, the IoC container can easily be used to weave the aspects before injecting the dependencies. This would otherwise requires a special compilation or a special ClassLoader.
Hope this helps.
Dependency injection was explained very well in How to explain dependency injection to a 5-year-old?:
When you go and get things out of the
refrigerator for yourself, you can
cause problems. You might leave the
door open, you might get something
Mommy or Daddy doesn't want you to
have. You might even be looking for
something we don't even have or which
has expired.
What you should be doing is stating a
need, "I need something to drink with
lunch," and then we will make sure you
have something when you sit down to
eat.
AOP - Aspect Oriented Programming - basically means that the source you write is modified with other code, based on rules located ELSEWHERE. This means that you can e.g. say "as the first line of every method I want a 'log.debug("entering method()")' in a central place and each and every method you compile with that rule in place will then have that line included. The "aspect" is the name of looking on code in other ways than simply from first source line to last.
Inversion of Control basically means that you do not have a central piece of code controlling everything (like a giant switch in main()) but have a lot of pieces of code that "somehow" get called. The subject is discussed at Wikipedia: http://en.wikipedia.org/wiki/Inversion_of_control
These three are all different concepts, but they all work well together, and so Spring apps often make use of all of it at once. I'll give you an example.
Let's say that we have a web application that can do many different things. We could construct this application in many ways, but one way is to create a class that is in charge of doing each of these things. We need to invoke and create these classes from somewhere. One option is to have a big main class that creates one of each of these services, opens up a socket, and passes calls to these services as they come in. Unfortunately, we've gone and created ourselves a god class, which has way too much logic and knows way too much about how everything in our program works. If we change anything about our program, we're probably going to need to modify this class.
Also, it's difficult to test. We can't test any class in isolation if it runs around instantiating and invoking the other classes directly. Unit tests become much, much harder to write.
A way to get around this is to use inversion of control. We say "okay, these are service classes. Who instatiates them? Not me." Usually, each one defines an interface, like LoginService or BillingService. There might be more than one implementation of that interface, but your app doesn't care. It just knows that it can ask for a certain kind of a service or a service with a certain name, and it'll get something nice back.
Dependency injection allows us to wire all of our litle pieces together. Classes have accessible fields, constructor arguments, or setter methods that are references to the other components that they'll need to access. That makes unit testing much easier. You can create the object under test, throw a mock or stub dependency at it, and then test that the object behaved correctly in isolation.
Now, our real application is a complex jumble of pieces that all need to be wired together just so. There are many ways to accomplish this, including allowing the application to make guesses ("this class wants a UserService, there is exactly one other class I'm in charge of that implements UserService") or by carefully explaining how they wire together in XML or Java. Spring, at its core, is a service that takes care of wiring these classes together.
Now we get to AOP. Let us say that we have all of these classes that are wired to each other in elaborate ways. There are some cross-cutting concerns that we might want to describe in very generic ways. For instance, perhaps you'd like to start a database transaction whenever any service is invoked, and commit that transaction so long as the service doesn't throw an exception. It turns out that Spring is in a unique position to perform such a task. Spring can create proxy classes on the fly that implement whatever interface your classes need, and it can wrap your class in its proxy. Now, IoC and dependency injection certainly aren't necessary to do aspect-oriented programming, but it's an extremely convenient way to accomplish it.
The difference between Dependency Injection and Inversion of Control is explained very well in
http://martinfowler.com/articles/dipInTheWild.html
("You mean Dependency Inversion, Right?" section)
The summary:
DI is about how one object acquires a dependency. When a dependency
is provided externally, then the system is using DI.
IoC is about who initiates the call. If your code initiates a call,
it is not IoC, if the container/system/library calls back into code
that you provided it, is it IoC.
let me tell you some word about AOP, hope it make it simplier to understand.
The very base principle of AOP is finding common tasks/aspects which returns in
many places in the code and dont belong to the concerete business of the code. For example
write to log on every entrance to any function, or when an object is created wrapp it, or send email to admin when calling to specific function.
So instead of the programmers will handle these non businuss aspect we take it from them and
we manage these aspects behond the scene.
That all the basic of AOP on 1 leg....
A simple comparison from Spring in Action:
Whereas DI helps you decouple your application
objects from each other, AOP helps you decouple cross-cutting concerns from the
objects that they affect.
My team is moving to Spring 3.0 and there are some people who want to start moving everything into Annotations. I just get a really bad feeling in my gut (code smell?) when I see a class that has methods like this: (just an example - not all real annotations)
#Transaction
#Method("GET")
#PathElement("time")
#PathElement("date")
#Autowired
#Secure("ROLE_ADMIN")
public void manage(#Qualifier('time')int time) {
...
}
Am I just behind the times, or does this all seem like a horrible idea to anyone else? Rather then using OO concepts like inheritance and polymorphism everything is now by convention or through annotations. I just don't like it. Having to recompile all the code to change things that IMO are configuration seems wrong. But it seems to be the way everything (especially Spring) is going. Should I just "get over it" or should I push back and try to keep our code as annotation free as possible?
Actually I think that the bad feeling in your gut against has more to do with Annotations like this mixing configuration with code.
Personally I feel the same way as you do, I would prefer to leave configuration (such as transaction definitions, path elements, URLs that a controller should be mapped to, etc.) outside of the code base itself and in external Spring XML context files.
I think though that the correct approach here comes down to opinion and which method you prefer - I would predict that half the community would agree with the annotations approach and the other half would agree with the external configuration approach.
Maybe you have a problem with redundant annotations that are all over the code. With meta-annotations redundant annotations can be replaced and your annotations are at least DRY.
From the Spring Blog:
#Service
#Scope("request")
#Transactional(rollbackFor=Exception.class)
#Retention(RetentionPolicy.RUNTIME)
public #interface MyService {
}
#MyService
public class RewardsService {
…
}
Because Java evolves so slowly people are putting more features that are missing in the language into annotations. This is a good thing Java can be extended in some form and this is a bad thing as most of the annotations are some workaround and add complexity.
I was also initially skeptical about annotations, but seeing them in use, they can be a great thing. They can also be over used.
The main thing to remember about annotations is that they are static. They cannot change at runtime. Any other configuration method (xml, self-description in code, whatever) does not suffer from this. I have seen people here on SO have issues with Spring in terms of having a test environment on injecting test configurations, and having to drop down to XML to get it done.
XML isn't polymorphic, inherited or anything else either, so it is not a step backwards in that sense.
The advantage of annotations is that it can give you more static checking on your configuration and can avoid a lot of verbosity and coordination difficulties in the XML configurations (basically keeping things DRY).
Just like XML was, Annotations can be over used. The main point is to balance the needs and advantages of each. Annotations, to the degree that they give you less verbose and DRYer code, are a tool to be leveraged.
EDIT: Regarding the comment about an annotation replacing an interface or abstract class, I think that can be reasonable at the framework boundary. In a framework intended to be used by hundreds, if not thousands of projects, having an interface or base class can really crimp things (especially a base class, although if you can do it with annotations, there is no reason you couldn't do it with a regular interface.
Consider JUnit4. Before, you had to extends a base class that had a setup and tear down method. For my point, it doesn't really matter if those had been on an interface or in a base class. Now I have a completely separate project with its own inheritance hierarchy, and they all have to honor this method. First of all, they can't have their own conflicting method names (not a big deal in a testing framework, but you get my point). Second of all you have have the chain of calling super all the way down, because all methods must be coupled.
Now with JUnit4, you can have different #Before methods in different classes in the hierarchy and they can be independent of each other. There is no equally DRY way to accomplish this without annotations.
From the point of view of the developers of JUnit, it is a disaster. Much better to have a defined type that you can call setUp and teardown on. But a framework doesn't exist for the convenience of the framework developer, it exists for the convenience of the framework user.
All of this applies if your code doesn't need to care about the type (that is, in your example, nothing would every really use a Controller type anyway). Then you could even say that implementing the framework's interface is more leaky than putting on an annotation.
If, however, you are going to be writing code to read that annotation in your own project, run far away.
It's 2018 and this point is still relevant.
My biggest problem with annotations is that you don't have an idea what the annotations are doing. You're cutting some caller code off and hiding it somewhere disconnected from the callee.
Annotations were introduced to make the language more declarative and less programmatic. But if you're moving the majority of the functionality to annotations, you are effectively switching your code to a different language (and not a very good one at that). There's very little compile-time checking. This article makes the same point: https://blog.softwaremill.com/the-case-against-annotations-4b2fb170ed67
The whole heuristic of "move everything to configuration so that people don't have to learn how to code" has gotten out of control. Engineering managers aren't thinking.
Exceptions:
JUnit
JAX-RS
I personally feel that annotations have taken over too much and have blown up from their original and super useful purpose (e.g., minor things like indicating overridden method) into this crazy metaprogramming tool. I don't feel the JAva mechanism is robust enough to handle these clusters of annotations preceding each method.
For instance, I'm fighting with JUnit annotations these days because they restrict me in ways that I don't like
That being said, in my experience the XML based configuration isn't pretty either. So to quote South Park, you're choosing between a giant douche and a t*rd sandwich.
I think that the main decision you have to make is whether you are more comfortable with having a delocalization of the spring configuration (i.e., maintain two files instead of one), and whether you use tools or IDE plugins that benefit from the annotations. Another important question is whether the developers who will use or maintain your code truly understand annotations.
Like many things, there are pros and cons. In my opinion, some annotations are fine, though sometimes it feels like there is a tendency to overuse annotations when a plain old function calling approach might be superior, and taken as a whole, this can unintentionally increase cognitive load because they increase the number of ways to "do stuff."
Let me explain. For example, I'm glad you mentioned the #Transactional annotation. Most Spring developers probably are going to know about and use #Transactional. But how many of those developers know how #Transactional actually works? And would they know off the top of their head how to create and manage a transaction without using the #Transactional annotation? Using #Transactional makes it easier for me to use transactions in a majority of cases, but in particular cases when I need more fine-grained control over a transaction, it hides those details from me. So in a way it is a double edged sword.
Another example is #Profile in Spring config classes. In the general case, it makes it easier to specify which profiles you want a Spring component loaded in. However, it if you need more powerful logic than just specifying a list of profiles for which you want the component loaded, you would have to get the Environment object yourself and write a function to do this. Again, most Spring developers would probably be familiar with #Profile, but the side effect of that is they become less familiar with the details of how it works, like the Environment.acceptsProfiles(String... profiles) function, for instance.
Finally, when annotations don't work, it can be harder to understand why and you can't just put a breakpoint on the annotation. (For instance, if you forgot the #EnableTransactionManagement on your config, what would happen?) You have to find the annotation processor and debug that. With a function calling approach, you can of course just put a breakpoint in the function.
Annotations have to be used sparingly. They are good for some but not for all. At least the xml configuration approach keeps the config in one file (or multiple) instead of spread all over the place. That would introduce (as I like to call it) crappy code organization. You will never see the full picture of the configuration if it is spread across hundreds of files.
Annotations often introduce dependencies where such dependencies do not belong.
I have a class which happens by coincidence to have properties which resemble the attributes from a table in an RDBMS schema. The class was created with this mapping in mind. There is clearly a relationship between the class and the table but I am happy to keep the class free from any metadata declaring that relationship. Is it right that this class makes a reference to a table and its columns in a completely different system? I certainly don't object to external metadata that associates the two and leaves each free of an understanding of the other. What did I gain? It is not as if metadata in the source code provides type safety or mapping conformance. Any verification tool that could analyze JPA annotations could equally well analyze hibernate mapping files. Annotations did not help.
At one contract, I had created a maven module with a package of implementations of interfaces from an existing package. It is unfortunate that this new package was one of many directories within a monolithic build; I saw it as something separate from the other code. Nonetheless, the team was using classpath scanning so I had to use annotations in order to get my component wired into the system. Here I did not desire centralized configuration; I simply wanted external configuration. XML configuration was not perfect because it conflated dependency wiring with component instantiation. Given that Rod Johnson didn't believe in component based development, this was fair. Nonetheless, I felt once again that annotations did not help me.
Let's contrast this with something that doesn't bother me: TestNG and JUnit tests. I use annotations here because I write this test knowing that I am using either TestNG or JUnit. If I replace one for the other, I understand that I will have to perform a costly transition that will stray close to a rewrite of the tests.
For whatever reason, I accept that TestNG, JUnit, QUnit, unittest, and NUnit owns my test classes. Under no circumstances does either JPA or Hibernate own those domain classes which happen to get mapped to tables. Under no circumstances does Spring own my services. I control my logical and physical packaging in order to isolate units which depend upon either. I want to ensure that a move away from one doesn't leave me crippled because of all the dependencies it left behind. Saying goodbye is always easier than leaving. At some point, leaving is necessary.
Check these answers to similar questions
What are the Pros/Cons of Annotations (non-compiler) compared to xml config files
Xml configuration versus Annotation based configuration
Basically it boils down to: Use both. Both of them have there usecases. Don't use annotations for things which should remain configurable without recompiling everything (especially things which maybe your user should be able to configure without needing you to recompile all)
I think it depends to some extent on when you started programming. Personally, I think they are horrid. Primarily because they have some quasi-'meaning' which you will not understand unless you happen to be aware of the annotation in question. As such they form a new programming language all by themselves and move you further away from POJOs. Compared to (say) plain old OO code. Second reason - they can prevent the compiler doing your work for you. If I have a large code base and want to refactor something or rename something I'd ideally like the compiler to throw up everything that needs to be changed, or as much as possible. An annotation should just be that. An annotation. Not central to the behaviour of your code. They were designed originally to be optionally omitted upon compilation which tells you all you need to know.
And yes, I am aware that XML config suffers in the same way. That doesn't make it worse, just equally bad. At least I can pretend to ignore that though - it doesn't stare me in the face in every single method or parameter declaration.
Given the choice I'd actually prefer the horrible old J2EE remote/home interfaces etc (so criticised by the Spring folks originally) as at least that gives me an idea of whats happening without having to research #CoolAidFrameworkThingy and its foibles.
One of the problems with the framework folks is that they need to tie you to their framework in order to make the whole enterprise financially viable. This is at odds with designing a framework well (i.e. for it to be as independant and removeable from your code as possible).
Unfortunately, though, annotations are trendy. So you will have a hard time preventing your team using them unless you are into code reviews/standards and the like (also, out of fashion!)
I read that Stroustup left annotations out of C++ as he feared they would be mis-used. Sometimes things go in the wrong direction for decades, but you can hope things will come full circle in time..
I think annotations are good if they are used with measure. Annotations like #WebService do a lot of work at deployment and run time, but they don't interfere in the class. #Cachexxx or #Transactional clearly interfere by creating proxies and a lot of artifacts, but I think they are under control.
Thing begin to mess when using Hibernate or JPA with annotations and CDI. Annotations grow a lot.
IMO #Service and #Repository are interferences of Spring in your application code. They make your application Spring dependant and only for Spring use.
The case of Spring Data Graph is another story. #NodeEntity, for instance, add methods to the class at build time to save the domain object. Unless you have Eclipse and Spring plugin you will errors because those methods don't exist in source code.
Configuration near the object has its benefits, but also a single configuration point. Annotations are good with measure, but they aren't good for everything, and definitively bad when there are as much annotation lines as source code lines.
I think the path Spring is going is wrong; mainly because in some cases there is no other way to do such funny things. It's is as if Spring wants to do xtreme coding, and at the same time they lock developers into Spring framework. Probably Java language needs another way to do some things.
Annotations are plain bad in my experience:
Inability to enforce type safety in annotations
Serialization issues
Cross compiling (to for instance javascript) can be an issue.
Libraries/frameworks requiring annotations exclude non-annotated classes from external libraries.
not overridable or interchangeable
your projects eventually becomes strongly dependant on the system that requires the annotations
If Java would have something like "method literals" you could annotate a class in a corresponding annotation class.
Something like as following:
Take for instance javax.persistence, and the following annotated class:
#Entity
class Person
{
#Column
private String firstname;
public String getFirstname() { return firstname; }
public void setFirstname(String value) { firstname = value; }
#Column
private String surname;
public String getSurname() { return surname; }
public void setSurname(String value) { surname = value; }
}
Instead of the annotations, I'd suggest a mapping class like:
class PersonEntity extends Entity<Person> {
#Override
public Class<Person> getEntityClass() { return Person.class;}
#Override
public Collection<PersistentProperty> getPersistentProperties() {
LinkedList<PersistentProperty> result = new LinkedList<>();
result.add(new PersistentProperty<Person>(Person#getFirstname, Person#setFirstname);
result.add(new PersistentProperty<Person>(Person#getSurname, Person#setSurname);
return result;
}
}
The fictional "#" sign in this pseudo java code represents a method literal, which, when invoked on an instance of the given class, invokes the corresponding delegate (signed with "::" since java 8) of that instance.
The "PersistentProperty" class should be able to enforce the method literals to be referring to the given generic argument, in this case the class Person.
This way, you have more benefits than annotations can deliver (like subclassing your 'annotate'-class) and you have none of the aforementioned cons.
You can have more domain-specific approaches too.
The only pre annotations have over this, is that with annotations you can quickly see whether you have forgotten to include a property/method. But this too can be handled more concise and more correct with better metadata support in Java (think for instance of something like required/optional like in Protocolbuffers)