Need some help to understand Anotations - Spring annotations - java

I am trying to learn Spring and Hibernate and i am really struggling to understand Annotations and how they work. Most of the example i am seeing on the Internet are annotation based examples so i need to understand how the annotations work first before i can learn Spring or Hibernate
I have an idea of what they are and what they are used for. I know that they replace the xml configuration. I.e. You can configure beans directly within Java code using annotations. What i dont understand is how to use them and when they can be used.
Trying to understand how this can be done i think it would be helpful if i see the difference between the two. I have here a simple Spring program. If i was to convert this sample program to use annotations what would i need to do?
The reason i want to do it this way is because the program i have provided below is one that i understand very well (an example from the Spring in Action book that i am currently reading). If it is converted to an annotations version i will get an idea as to how and where annotations can be used.
Any suggestions?
Thanks in advance
instrumentalist.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="saxophone" class="com.sia.ch1.instrumentalist.Saxophone" />
<bean id="piano" class="com.sia.ch1.instrumentalist.Piano" />
<!-- Injecting into bean properties Ken 1 -->
<bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
<property name="song" value="Jingle Bells"/>
<property name="instrument" ref="piano"/>
</bean>
</beans>
Instrumentalist interface
package com.sia.ch1.instrumentalist;
public interface Instrument {
void play();
}
Instrumentalist implementor
package com.sia.ch1.instrumentalist;
import com.sia.ch1.performer.PerformanceException;
import com.sia.ch1.performer.Performer;
public class Instrumentalist implements Performer{
private Instrument instrument;
private String song;
public Instrumentalist(){}
public void perform() throws PerformanceException{
System.out.print("Playing " + song + " : ");
instrument.play();
}
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
public void setSong(String song) {
this.song = song;
}
}
Instruments - Piano
package com.sia.ch1.instrumentalist;
public class Piano implements Instrument{
public Piano(){}
public void play(){
System.out.println("PLINK PLINK");
}
}
Instruments - Saxophone
package com.sia.ch1.instrumentalist;
public class Saxophone implements Instrument{
public Saxophone(){}
public void play(){
System.out.println("TOOT TOOT TOOT");
}
}
Main class
package com.sia.ch1.instrumentalist;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.sia.ch1.performer.PerformanceException;
import com.sia.ch1.performer.Performer;
public class InstrumentalistApp {
public static void main(String[] args){
ApplicationContext ctx = new FileSystemXmlApplicationContext("c:\\projects\\test\\conf\\instrumentalist.xml");
Performer performer = (Performer) ctx.getBean("kenny");
try {
performer.perform();
} catch (PerformanceException e) {
e.printStackTrace();
}
}
}
Exception
package com.sia.ch1.performer;
public class PerformanceException extends Exception {
public PerformanceException() {
super();
// TODO Auto-generated constructor stub
}
public PerformanceException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public PerformanceException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public PerformanceException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
Edit 1
To try and convert the above i am going through these two simple examples:
Ex1: http://jroller.com/habuma/entry/reducing_xml_with_spring_2
Ex2: http://www.theserverside.com/tutorial/Spring-Without-XML-The-Basics-of-Spring-Annotations-vs-Spring-XML-Files
I kind of understand the examples in the first URL but the second one confused me a bit. In the example in the second URL, what is purpose of the SummaryConfig class? It looks as though the SummaryConfig class is a Java version of the XML file. This approach was not used in the example in the first example. What is the difference between the two?
Could it be that when you using annotations you can put the configuration details in a Java class (e.g. SummaryConfig) and you can also put the annotations in the beans themselves as in the examples in the first URL?
Thanks
Edit 2
Here is what i have done so far,
I have modified the xml document to remove the configuration and enable the auto-scan of components (Note: i changed the package name for the modified versions)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.sia.ch1.instrumentalist.annotate" />
</beans>
Added the #Component annotation to the Piano and Saxophone classes. I think this tells the container that this class should be included in the classes to be auto-scanned. right?
package com.sia.ch1.instrumentalist.annotate;
import org.springframework.stereotype.Component;
#Component
public class Piano implements Instrument{
public Piano(){}
public void play(){
System.out.println("PLINK PLINK");
}
}
package com.sia.ch1.instrumentalist.annotate;
import org.springframework.stereotype.Component;
#Component
public class Saxophone implements Instrument{
public Saxophone(){}
public void play(){
System.out.println("TOOT TOOT TOOT");
}
}
This is where i am stuck (the Instrumentalist class).
Is the #Component annotation required in this class? Or is it only required if the class is to be referenced from another class?
I know that i need to #Autowire the instrument and song properties but how do i know if i want to autowire byname or bytype etc
How would i autowire the String property if in this class there is no bean that represents it? i.e the instrument property would refer to the piano class but what would the song property be autowired with?
package com.sia.ch1.instrumentalist.annotate;
//
import org.springframework.stereotype.Component;
import com.sia.ch1.performer.PerformanceException;
import com.sia.ch1.performer.Performer;
//
#Component
public class Instrumentalist implements Performer{
private Instrument instrument;
private String song;
public Instrumentalist(){}
public void perform() throws PerformanceException{
System.out.print("Playing " + song + " : ");
instrument.play();
}
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
public void setSong(String song) {
this.song = song;
}
}
I think i am right in that no annotations are required on any of the other classes.
Thanks

This is where i am stuck (the Instrumentalist class).
Is the #Component annotation required in this class? Or is it only
required if the class is to be referenced from another class?
Yes, it is, if you want the annotation scanning to create the bean from the class for you without separate xml-configuration. Since you ask for an Instrumentalist -implementation with the bean name kenny (by name, not by type Instrumentalist) in your main-method, it also needs to be named.
Classes annotated with #Component, #Repository, #Controller and #Service are the ones that Spring scans for when the ApplicationContext is configured. The difference between these four annotations is semantical (differentiating the role of the class in the code), they all do exactly the same thing (unless for example you have some AOP-stuff that handles only certain annotation-types; for now you don't need to care about this).
Annotating a class with of any of the aforementioned annotation is same as declaring a bean in the xml:
<bean id="saxophone" class="com.sia.ch1.instrumentalist.Saxophone"> ... </bean>
is same as
#Component
public class Saxophone implements Instrument{
Note that by default the bean is named same as the class, except the first letter of the class name is changed to lowercase (so #Component public class SomeClass would create a bean called "someClass").
If you want to name your bean, you give the name as a parameter to the annotation:
#Component("kenny")
public class Instrumentalist implements Performer {
is same as
<bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
Another way to give the parameter to the annotation would be using #Component(value="kenny"). The reason the value= -part is optional, is because the annotations work like this: if there is only one parameter given without telling the field-name and the annotation contains a field called value, the parameter will be set to the value-field. If the field name is something else, or you want to set multiple fields of the annotation, you need to explicitly define the fields: #SomeAnnotation(field1="some string", field2 = 100) or #SomeAnnotation(value="someValue", anotherField="something else"). This is a bit besides the point, but it's good to know, as it can be confusing at first.
So, the #Component-annotation tells the Spring context that you want to create a bean (or beans, see #Scope) from the annotated classes. When there's no #Scope -annotation set, the beans will be created as singletons by default (you can autowire the bean to multiple classes, but they all see the same, single instance). For more information about the different scopes, I suggest reading the official documentation.
I know that i need to #Autowire the instrument and song properties
but how do i know if i want to autowire byname or bytype etc
Usually, if you only have a single implementation of a type (interface), it's more convenient to autowire by type. Autowiring by type works, when there is only a single implementation, because otherwise Spring cannot decide which implementation to instance and inject.
In your case you have two different classes implementing the Instrument-interface: Saxophone and Piano. If you try to autowire by-type the Instrument-field of the Instrumentalist, you will get an exception when Spring is constructing the Instrumentalist-bean:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.sia.ch1.instrumentalist.annotate.Instrument] is defined: expected single matching bean but found 2: [piano, saxophone]
Since there are two Instrument-implementations, Spring doesn't have enough information to determine which one you want injected in the Instrumentalist. This is where the #Qualifier -annotation steps in. With the #Qualifier, you tell Spring to inject the autowired dependency by-name. To inject the Piano-implementation of Instrument using the #Qualifier in the Instrumentalist is done by:
#Component(value="kenny")
public class Instrumentalist implements Performer
{
#Autowired
#Qualifier("piano")
private Instrument instrument;
is same as
<bean id="kenny" class="com.sia.ch1.instrumentalist.Instrumentalist">
<property name="instrument" ref="piano"/>
</bean>
Note that there's no need (but you can if you want to) to use #Component("piano") in the Piano-class, as the default naming changes the first letter of the class to lowercase and then uses it as the bean-name.
How would i autowire the String property if in this class there is no bean that
represents it? i.e the instrument property would refer to the piano class but what would > the song property be autowired with?
This is where the line is drawn with annotations (AFAIK); you cannot declare a bean of type String with annotations (Since java.lang.String is not an interface, cannot be extended as it's final and doesn't have an interface). However, with xml-configuration this is possible:
<bean id="songName" class="java.lang.String">
<constructor-arg value="Valley of the Queens"/>
</bean>
You can mix-and-match XML and annotations, and refer to beans declared in xml from annotations and vice versa, to inject this bean into Instrumentalists' song-field:
#Autowired
#Qualifier("songName")
private String song;
Hope this helped you to understand Springs' annotations in general and get started, I'd still strongly suggest you to read the official documentation, as there's a LOT more. If you prefer to read books instead of from screen, I'd suggest for example Appress's Spring Recipes (but I'm sure there are many other good books too).

Annotations could be used as markers like marker interfaces
class Foo implements java.io.Serializable{
...
}
Serializable is just a marker interface so that your application can know information about
the class at runtime (basically by reflection).
The problem with marker interfaces is that you can't use them to mark fields or methods,this why annotations were introduced.
assume that you have this annotation
public #interface myAnnotation{
}
you can simply get methods or fields which are decorated by this marker at run-time.
Hibernate and Spring as many frameworks require some information about your code or classes ,how would you achieve this,if you were the developer of these frameworks ?of course annotations are the best solution(at least the cleaner way)
Don't consider marker interfaces obsolete.There is also some advantages for using markers because they ensure type safety.
void M(Serializable s)
you can't pass any object to this method unless it implements the Serializable marker.For more details consider reading Effective Java there is a great explanation there.

Related

How to pass object as parameter to a spring aspect?

Let's say I need to enhance the shower() method with a #MusicAround advice to give me some music before and after executing the shower() method.
public class Me {
#MusicAround
public void shower() {
// shower code omitted
}
}
First I created the new annotation #MusicAround.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface MusicAround {
Then bind it with an aspect MusicAspect.
#Aspect
public class MusicAspect {
#Around("#annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint) throws Throwable {
IPhone iphone = new IPhone();
Iphone.music();
joinPoint.proceed();
iphone.music();
}
}
Configure MusicAspect as a Bean. #EnableAspectJAutoProxy annotation leaves spring to encapsulate the aspect proxy for me.
#Configuration
#EnableAspectJAutoProxy
public class ApplicationConfig {
// ... other beans omitted
#Bean
public MusicAspect musicAspect() {
return new MusicAspect();
}
}
In main method, get Me instance from context, and execute shower() method.
public static void main(String[] args) {
try {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Me me = context.getBean(Me.class);
me.shower();
context.close();
} catch (ApplicationContextException ace) {
// handle exception
}
}
Now I can enjoin the music during the shower.
<hey jude>
I'm showering
<don't be so serious>
The problem is that in this way MusicAspect class is coupled with IPhone class. I want to decouple them by injecting IPhone object as a parameter as below,
#Aspect
public class MusicAspect {
#Around("#annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint, IPhone iphone) throws Throwable {
iphone.music();
joinPoint.proceed();
iphone.music();
}
}
Of cause a second parameter "iphone" in musicAround() method will not be allowed here. Is there any spring features that I can use to decouple IPhone and MusicAspect in this case?
!Note: thanks #kriegaex for the proofreading.
This is a preliminary answer, because the content is not suitable for a comment.
When looking at the code in your updated question, some things strike me as strange:
I wonder why everyone is so eager to always use aspects in combination with annotations. Why not use a pointcut which directly targets packages, classes or methods of interest? All this annotation pollution is horrible, if not absolutely necessary. Ideally, the application code should be completely agnostic of the existence of aspects.
You use the #annotation pointcut designator incorrectly. Instead of #annotation(#MusicAround) it should be #annotation(MusicAround). But also that only works if the annotation happens to be in the exact same package as the aspect, otherwise you need #annotation(fully.qualified.package.name.MusicAround).
You use a MusicAspect, but then declare a MinstrelAroundAdvice bean. That does not seem to match. Besides, an aspect is an aspect, the method inside it which actually does something is the advice. So the class name *Advice for an aspect is simply wrong. Better use *Aspect instead or something else which properly describes what the aspect does. In this case, MusicAspect seems just fine to me.
Now concerning your actual question, it is still unclear to me. Is it about how to inject (auto-wire) another bean into an aspect instance?
Of course I was not allowed to do so.
Why "of course"? What was not allowed? How did you notice? Did something not work? Did you get an error message? A stack trace? Please explain clearly what you tried, what the expected result is and what happened instead. Make your problem reproducible. Your code snippets do not do that, unfortunately. Just imagine for a minute that someone else would ask you the same question without you seeing the full code and without other context information necessary to understand the problem. Could you answer it? If your helpers do not understand the problem, how can they answer your question? Please be advised to learn what an MCVE is.
Problem solved with the help of #k-wasilewski and #kriegaex. Thanks bro.
The answer is #Autowired annotation.
Define IPhone as a field of MusicAspect class. Add #Autowired tag, which tells spring context to initialize the IPhone instance for us.
#Aspect
public class MusicAspect {
#Autowired
private IPhone iphone;
#Around("#annotation(MusicAround)")
public Object musicAround(ProceedingJoinPoint joinPoint) throws Throwable {
Iphone.music();
joinPoint.proceed();
iphone.music();
}
}
Don't forget to register IPhone bean in ApplicationConfig. The rest part remain the same.
#Configuration
#EnableAspectJAutoProxy
public class ApplicationConfig {
// ... other beans omitted
#Bean
public IPhone iphone() {
return new IPhone();
}
}
The code passed unit-test on my laptop.

Is it OK to inject value directly inside Bean function?

I was wondering how to do dependency injection in the most effective way inside my code.
I have this code:
#Configuration
public class SomeName {
#Autowired
private Other other;
#Bean
public void method() {
other.someMethod();
// some code
}
}
Can this code be changed into the following code(other will be used only inside this function)?
#Configuration
public class SomeName {
#Bean
public void method(Other other) {
other.someMethod();
// some code
}
}
You should avoid #Autowired if possible and inject using a constructor or method.
Starting with Java 9 and java modules (project jigsaw) there are some strict rules that make it harder for your framework to change the values of a private field.
What Spring is doing in the first example is essentially that - it breaks encapsulation to change the value of a private value. (There is a way to overcome this with "opens" directive in module-info..)
You are also becoming dependent on the framework you are using and your code becomes harder to test compared to when using a simple setter.
You are also not explicitly declaring that your class depends on another class since I can easily instantiate it and "Other" will be null.
Some resources:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-scanning-autodetection (search for jigsaw)
https://blog.marcnuri.com/field-injection-is-not-recommended/
PS: You are probably missing #Configuration on your class

Spring AOP - Point Cut not getting called

I have a SpringBoot Application.
I have defined an Annotation say "Track", and I have annotated few methods in different packages which I want aop to consider.
The annotation has been defined as below :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Track {
}
I have not missed the #EnableAspectJAutoProxy in the #Configuration class of my package.
I have a Pointcut and an Advice defined in the Aspect like below :
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(#Track * *.*(..))")
void annotatedMethod() {
// No Implementation required
}
#Around("annotatedMethod() && #annotation(methodLevelTrack)")
public void adviseAnnotatedMethods(ProceedingJoinPoint proceedingJoinPoint,
Track methodLevelTrack) throws Throwable {
// do some task
proceedingJoinPoint.proceed();
// do some task after the method is executed.
}
}
My intention is: for any method (annotated with #Track) in any package, with any access modifier, and any number of input arguments, and any return type, to follow the aspect's #Around advice.
Now, the interesting situation is as below :
I have a class say "Engine" which calls other classes and downstream systems to perform a long-running operation. Let's define the class as follows :
public class Engine {
// bunch of other autowired objects
public void processTask() {
<autowired_object_A>.someMethod() // this method has been annotated with #Track
<autowired_object_B>.someMethod() // this method has also been annotated with # Track
.... // bunch of other methods in other autowired objects that have been annotated with # Track
someMethodOfEngineClass(); // Now this has been defined in the Engine class as below, but pointcut doesn't recognize this method!
}
#Track
private void someMethodOfEngineClass() {
// do something
}
}
All the "other" autowired objects' methods are getting recognized by pointcut as expected but the method within this Engine class, that has been annotated with #Track, is not recognized. What's the mystery?
I have tried making "someMethodOfEngineClass" method public, return something instead of void and all those combinations and it doesn't work.
What am I missing?
Is it the pointcut definition expression?
I have defined the aspect in one of the sub packages, is aspect supposed to be defined at the top level in the package structure?
Can you folks please suggest something that can work? I am kinda stuck at this.
When you define aop spring creates proxy around the class,
so when the method is called, actually call is delegated to proxy, sth like
your.package.Engine$$FastClassBySpringCGLIB$$c82923b4.someMethodOfEngineClass()
But this works only when a method is called from outside it's class
If you call class method from the same class you are effectively calling it by this.someMethodOfEngineClass()
here -> http://www.nurkiewicz.com/2011/10/spring-pitfalls-proxying.html
you can find more info about proxying
so proxy is bypassed and aop is not working.

Can't autowire a component into a utility class

I'm having a problem autowiring a component into a utility class. The utility class initially had static methods in it, but then I just made them instance methods.
I defined the utility class with #Component and within the class put in
class MyUtilityClass {
#Autowired
ExistingComponent existingComponent
...
}
The package the utility class is in is under the specified parent directory for #ComponentScan, where value="top-level-directory" that also contains the packages for all the other autowired components.
To get the utility class to run I had to pass the ExistingComponent into a constructor for the utility class.
Using Spring 4.1.6.
This is probably something basic, but it's not clicking. What am I missing here?
Thanks.
UPDATE 1
The class that is calling the utility class looks like the following:
class UsingClass {
#Autowired
MyUtilityClass myUtilityClass
...
def method1() {
String variable1 = "some data"
myUtilityClass.utilityMethod(variable1)
...
}
}
Originally I had the internal utility method as static and tried to use the utility class without autowiring it.
Do you have this somewhere within your beans XML configuration files?
<context:component-scan base-package="com.your.package" />
The base-package indicates where your components are stored.
This allows Spring to scan the package so that it can find the beans annotated with #Component.
This is explained in more depth here.

EJB Dependency Injection with interface

I have an interface I with method m and two concrete implementations A and B.
public interface I{
public void m();
}
public class A implements I{
public void m(){
//
}
}
public class B implements I{
public void m(){
//
}
}
I want to know when I inject I which of the two methods will be executed
#EJB
private I service;
///
service.m();
/////
None of them, it will become into an error since the application server doesn't know which implementation to use. To avoid this, just provide the id of the class implementation, which by default is the same name of the class but starting with lower case:
//uncomment one of these
//#EJB(name="a")
//#EJB(name="b")
private I service;
None of them. The code will compile, but you won't be able to deploy it on your application server. Without specifing type of injected class, you will get an Exception similar to this:
org.jboss.weld.exceptions.DeploymentException:WELD-001409 Ambiguous dependencies
for type [...] with qualifiers [...] at injection point [...]. Possible dependencies
[...] with qualifiers [...], Managed Bean [...] with qualifiers [...]
Container (i.e. your application server) won't be able to recognize which field do you really want to inject (A or B). It cannot just guess it out of thin air. To avoid this kind of errors, provide it with annotation (called qualifier) specifying whether you want to inject class A or class B. If you want an example, you should see this article.

Categories