I have a #SpringBootTest that autowires a #Repository which returns an #Entity. I have no specific ComponentScanning declared.
This works as long as the Repo is in a package my.repo and the entity and test are in package my.model
If I move all three to package my.repo I get "Not a managed type" for the model.
If I move all three to package my.model I get "No qualifying bean of type" for the repo.
I know about the recommended package structure. But is it more than a recommendation? Are there strict rules for the packages hardcoded?
As long as your #Repository is in the same package with other classes/entities, it doesnt need any scanning. But yes if you choose to use a different package, you must tell spring to scan your specific packages for your #Repositoy(ies). So somewhere in your #Configuration class, use this:
#ComponentScan(basePackages = "someuniq.packagename.goeshere").
For an example - like this.
I need to add an annotation to a class which is in a sperate dependency (in a separate jar) of the project that I am working on. I am wondering that can I do this in Java?
As an example, I need to add an annotation HisClass without touching the source code of HisClass.
public class HisClass{
// ...
}
So, that the above class should be look like below at the build time,
#MyAnnot ( me = MyClass.class )
public class HisClass{
// ...
}
There are many ways:
Write a compiler plugin for javac, and make it add the annotations. This will be quite difficult, as the plugin API has nearly no documentation.
2.(Maybe not possible) Inject the annotation after compiling. Add an extra buildstep after compiling and use a library like ASM to add this annotation to the classfile.
I have a class that's located in a package. In that package I have several JPAEntities. However all I want for the JPAAnnotationProcessor to do is to generate QModel for a single class. Not for all classes inside that package. Is that possible without moving the class to another package?
You can use #QueryExclude annotation on top of the classes for which you don't want QClass to be generated.
import com.mysema.query.annotations.QueryExclude
#Entity
#QueryExclude
public class MyEntity {}
Unfortunately it is not possible to solve the problem in package level atm. If you mark all package with #QueryExclude and single class with #QueryEntity, still the whole package will be excluded. Therefore you have to mark each class separately.
In my current project I would like to store some configuration data in a package annotation and to access it by some CDI producers. If the annotation is not found in the current package the producers will search for it upward in the package hierarchy.
So far so good. Unfortunately it seems so that I can access an existing package via Package.getPackage("my.package") only after the first access to one of its classes or interfaces.
The following example illustrates this behaviour:
Class in package a.b
package a.b;
public class ClassInMitte {
}
Example programm to access the package oben.mitte
package other;
public class Refl {
public static void main(String[] args)
{
Package viaName = Package.getPackage("a.b");
System.out.println(viaName.getName());
System.out.println(viaName.hashCode());
}
}
Running Refl results in a NullPointerException. But if I add new ClassInMitte() as first statement I can access the package information. Somehow I must access the content of a package before I can access the package information itself. This makes sense since otherwise the classloaders must scan the whole classpath while starting.
But netherless is there an easy way to access package information without accessing the content of the package before? I know I could use frameworks like reflections but a 'lightweight' solution would be my prefered solution.
Package.getPackage only returns packages that are already known to the current class loader, and the only way to do that is by loading a class from that package. It's basically a wrapper for ClassLoader.getPackage.
I'm using Spring 3.1 and bootstrapping an application using the #Configuration and #ComponentScan attributes.
The actual start is done with
new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);
This Configuration class is annotated with
#Configuration
#ComponentScan("com.my.package")
public class MyRootConfigurationClass
and this works fine. However I'd like to be more specific about the packages I scan so I tried.
#Configuration
#ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass
However this fails with errors telling me it can't find components specified using the #Component annotation.
What is the correct way to do what I'm after?
Thanks
#ComponentScan uses string array, like this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
When you provide multiple package names in only one string, Spring interprets this as one package name, and thus can't find it.
There is another type-safe alternative to specifying a base-package location as a String. See the API here, but I've also illustrated below:
#ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})
Using the basePackageClasses specifier with your class references will tell Spring to scan those packages (just like the mentioned alternatives), but this method is both type-safe and adds IDE support for future refactoring -- a huge plus in my book.
Reading from the API, Spring suggests creating a no-op marker class or interface in each package you wish to scan that serves no other purpose than to be used as a reference for/by this attribute.
IMO, I don't like the marker-classes (but then again, they are pretty much just like the package-info classes) but the type safety, IDE support, and drastically reducing the number of base packages needed to include for this scan is, with out a doubt, a far better option.
Provide your package name separately, it requires a String[] for package names.
Instead of this:
#ComponentScan("com.my.package.first,com.my.package.second")
Use this:
#ComponentScan({"com.my.package.first","com.my.package.second"})
Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.
#ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})
If you look into the ComponentScan annotation .class from the jar file you will see a basePackages field that takes in an array of Strings
public #interface ComponentScan {
String[] basePackages() default {};
}
Or you can mention the classes explicitly. Which takes in array of classes
Class<?>[] basePackageClasses
You use ComponentScan to scan multiple packages using
#ComponentScan({"com.my.package.first","com.my.package.second"})
You can also use #ComponentScans annotation:
#ComponentScans(value = { #ComponentScan("com.my.package.first"),
#ComponentScan("com.my.package.second") })
I use:
#ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
make sure you have added this dependency in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Use
#ComponentScan(basePackages = {"package1", "package2"})
define it at top before class.
Edit: the brackets must be around all the base packages, not a pair of brackets per package