Springboot #EntityScan not working - java

I have a Springboot application and my entity model is separated from my main application included as dependency.
my Application.java is located in this package com.a.b.c
#SpringBootApplication
#EntityScan("com.a.b")
public class Applciation
{
public static void main(String args[])
{
SpringApplication.run(Applciation.class, args);
}
}
and my entity model is located in another project inside this package com.a.b
But I'm getting an error: Caused by: java.lang.IllegalArgumentException: Not a managed type: class

I can relate to you. I have spent countless hours regarding this.
I'll divide your question to 3 parts (I will use "entity-project" and "spring-project" to refer to the project containing entity classes and main project trying to incorporate entity classes) :
Part 1 of 3: Making sure your entity classes are exposed in entity-project.
Create a Config at the root of entity-project
package com.a.b
#Configuration
#Import ({Entity1.class, Entity1Repo.class, Entity1Key.class,
Entity2.class, ... })
class EntityConfig {}
Part 2 of 3: Making sure your entity classes are in the classpath of spring-project.
Since you are using SpringBoot, I'm sure you are using maven (or Gradle).
Anyway, make sure you maven install the entity-project with entity classes:
cd /path/to/entity-project/
mvn install -DskipTests
In spring-project's maven file, include to the entity-project.
Part 3 of 3: Use the EntityScan annotation.
It is just my taste, but I prefer using basePackageClasses instead of basePackage.
#SpringBootApplication
#EntityScan(basePackageClasses = {Entity1.class})
// use basePackageClasses to avoid type errors
#Import({com.a.b.EntityConfig.class}) // this is what you are missing
public class Applciation
{
public static void main(String args[])
{
SpringApplication.run(Applciation.class, args);
}
}
Viola!

Related

Spring Boot #Autowired does not work with class of different package

The structure of my project like the following:
I am sure everything okay but only one thing make the problem is #Autowired in StoredProcedureSpringDataJpaApplication.java like the following:
public class StoredProcedureSpringDataJpaApplication implements CommandLineRunner {
#Autowired
private StudentRepository stu;
public static void main(String[] args) {
SpringApplication.run(StoredProcedureSpringDataJpaApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
List<Student> students = stu.findAll();
students.forEach(System.out :: println);
}
}
Error description is:
Field stu in com.example.demo.StoredProcedureSpringDataJpaApplication required a bean of type 'com.repository.StudentRepository' that could not be found.
I know this is familiar question ,I did so many way to try to solve this problem in the internet even in stackoverflow but all can not solve my problem.
Help me solve this problem.
Use #ComponentScan({"com.example.demo", "com.repository"})
By default without this annotation it considers only annotations that exist inside the package where your #SpringBootApplication is declared, aka com.example.demo
Also together with the #ComponentScan use the following
#EnableJpaRepositories(basePackages = {"com.repository"})
Your package structure is incorrect StoredProcedureSpringDataJpaApplication.java should be in the root package. Another way is component scan placing annotation over StoredProcedureSpringDataJpaApplication.java. In your case, it should be like
This won't work for the repository class and as you have a different package structure so #EnableJpaRepositories(basePackages = "com.repository") will help you resolve this issue.
This happens because #SpringBootApplication does only scan in the package where it is defined.
Make sure it is placed at the root of your project and everything that should be scanned below it. For example:
com
- example
- demo
- StoredProcedureSpringDataJpaApplication.java
- repository
- StudentRepository.java

No qualifying repository test in Spring

I'm using Spring 2.4 and jUnit 5.7.
I'm trying to use a repository create for test but I'm getting "No qualifying bean of type".
I annotated the repository #TestComponent.
package com.cjgmj.dynamicQuery.persistence.repository;
import org.springframework.boot.test.context.TestComponent;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.cjgmj.dynamicQuery.persistence.entity.DummyEntity;
#TestComponent
public interface DummyRepository extends JpaSpecificationExecutor<DummyEntity> {
}
And I'm trying to get it on my Test class.
#SpringBootTest
public class TextLikeSpecificationTests {
#Autowired
private DummyRepository dummyRepository;
...
}
The project structure is:
- src/test/java
|- projectPackage
|- persistence
|- entity
|- DummyEntity
|- repository
|- DummyRepository
I tried place the repository and the entity on main package, and also without annotation in the repository, but I'd got the same error.What I'm doing wrong?
Thank you in advance.
I just solved this problem. The first step was change the repository to extends JpaRepositoryImplementation. Then it throws a UnsupportedOperationException. Diging a bit I reach this post and I changed all the Collections.emptyList and Arrays.asList() to instanciate it as new ArrayList<>(). Then the test run properly.

Exclude #SpringBootApplication

I have 2 mains in my project
#SpringBootApplication
#ComponentScan(value = com.somepackage,
excludeFilters = {#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Class2.class)})
public Class1
and
#SpringBootApplication
#ComponentScan(value = com.somepackage,
excludeFilters = {#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Class1.class)})
public Class2
They are both in the same package, but need to scan some other packages.
When I run in my IDE Class1 I don't want Class2 to be loaded and when I run Class2 I don't want Class1 to be loaded.
Doing these exclusion doesn't work and doing #SpringBootApplication(exclude = Class2.class) display this error: The following classes could not be excluded because they are not auto-configuration classes
How can I exclude the other SpringBootApplication class ?
EDIT:
We are using 2 main classes because we want to have some tools (little scripts) and reuse some part of the code. Example: I have the main class of the application but I want to run some part of it with another main to do some cleanup but very rarely and don't want to setup a lot of libs just to do this. I know it's not clean, but I want to write some main rapidly to invoke my application with all the other bean loaded but not with the first main because it starts a lot of other thread that I don't need.
I think you have to change you application structure to minimal 3 modules:
Core code and resources (shared logic)
Application 1 code and resources (use the core module)
Application 2 code and resources (use the core module)
That makes thing easier and more clear. In the application modules you can implement interfaces or extends basic/default configuration from the core.
With this approach you don't have to use complex include/exclude logic for specific classes in you application main classes.
You could work with profiles using whatever name makes sense for your case.
#SpringBootApplication
#Profile("!test")
public Class1 {}
#SpringBootApplication
#Profile("test")
public Class2 {}

Spring Boot: How to include a configuration class that is not in my base package?

I've got a fairly standard spring boot app which is built with gradle from several gradle modules. Here's the directory layout:
- root
- serviceA
- src/main/java
- org.example.serviceA
- ServiceAApplication.java
- serviceB
- serviceC
- common
- src/main/java
- org.example.common
- CommonSecurityConfiguration.java
What I would like to do is to include the CommonSecurityConfiguration class from the shared common module in serviceA. Note that ServiceAApplication and CommonSecurityConfiguration reside in different base packages.
I tried to use #Import(CommonSecurityConfiguration.class) on my ServiceAApplication, but that had no observable effect at all.
The only thing which worked was to annotate ServiceAApplication like so:
#SpringBootApplication(basePackages = { "org.example.serviceA", "org.example.common"})
public class ServiceAApplication { ... }
This approach works, but seems very coarse grained to me - it will import each and every component and configuration it finds in org.example.common.
Is there a better way to do this? Can I include individual classes into the component scan by listing them one by one?
Try to use
#Import(CommonSecurityConfiguration.class) above configuration class. So it would look like this:
#Configuration
#Import(CommonSecurityConfiguration.class)
public class ServiceAConfiguration { ... }
I believe what you are looking for is #CompnentScan("com.example"), this will tell Spring to look at all the files under the specified path recursively. (In this case it would be #ComponentScan("root"))
You find more info here: baeldun.com/spring-component-scanning
Hope this helps.
Since you want to control which components are brought in , we can make an annotation , let's call that annotation PickyComponentImport
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface PickyComponentImport{
}
Then on our SpringBootApplication annotation we can add a new filter which looks for this annotation.
#ComponentScan(basePackages = { "org.example.serviceA",
"org.example.common" }, includeFilters = #Filter(PickyComponentImport.class))
public class ServiceAApplication { ... }
Then we can just add that annotation on any class we want included
#Configuration
#PickyComponentImport
public class CommonSecurityConfiguration {
}
EDIT: I think if you go with this approach you can just componentScan basepackage as root.

gwt-test-utils does not find my entry point class

I am trying to get gwt-test-utils to work. I set up the project in the following way:
src/main/java : all the java source code
src/test/java : the test source code
src/test/resources : resource files for the tests
I am building my project with gradle and eclipse. Gradle uses these directories correctly by default and I added all three of them as source directories to Eclipse.
I have successfully built and run the project and was able to execute some plain old JUnit tests as well as a GWTTestCase, so I think I set up the project and its dependencies correctly.
Now I wanted to use gwt-test-utils for some more advanced integration tests. To do so I did the following:
Add the gwt-test-utils and gwt-test-utils-csv to my dependencies
gwtTestUtilsVersion = '0.45'
testCompile group:'com.googlecode.gwt-test-utils', name:'gwt-test-utils', version:gwtTestUtilsVersion
testCompile group:'com.googlecode.gwt-test-utils', name:'gwt-test-utils-csv', version:gwtTestUtilsVersion
Add a gwt-test-utils.properties file to the directory src/test/resources/META-INF with the following content:
path/to/my/module = gwt-module
Added a class that extends GwtCsvTest to a package in the src/test/java directory. It is modeled after the second example in HowToWriteCsvScenario from the gwt-test-utils project wiki, replacing occurrence of their example classes with mine. It looks like this
#CsvDirectory(value = "gwtTests")
public class LoginLogoutTest extends GwtCsvTest
{
#Mock
private MainServiceAsync mainService;
private AppController appController = new AppController();
#CsvMethod
public void initApp()
{
appController.onModuleLoad();
}
#Before
public void setup()
{
GwtFinder.registerNodeFinder("myApp", new NodeObjectFinder()
{
#Override
public Object find(Node node)
{
return csvRunner.getNodeValue(appController, node);
}
});
GwtFinder.registerNodeFinder("loginView", new NodeObjectFinder()
{
#Override
public Object find(Node node)
{
return csvRunner.getNodeValue(appController.getRootPresenter().getCurrentlyActiveSubPresenters().iterator().next().getView(), node);
}
});
addGwtCreateHandler(createRemoteServiceCreateHandler());
}
}
added a csv-file for configuring the test to src/test/resources/gwtTests with the following content
start
initApp
assertExist;/loginView/emailTextBox
I tried executing it via the Eclipse's Run As > JUnit Test and indirectly via gradle build (which executes all the test cases, not just this one). Both lead to the same error:
ERROR GwtTreeLogger Unable to find type 'myPackage.client.AppController'
ERROR GwtTreeLogger Hint: Check that the type name 'myPackage.client.AppController' is really what you meant
ERROR GwtTreeLogger Hint: Check that your classpath includes all required source roots
The AppController class is the entry-point configured in the module I configured in gwt-test-utils.properties, which makes me think that configuration works correctly and the rest of the setup (dependencies and all) work as well.
In an earlier version I used the same file as a subclass of GWTTestCase and created an AppController instance in the same way. That worked, so I'm pretty sure the class path is setup correctly to include it as well. I also tried changing it back to the previous version just now and it still works.
I have no clue why the class is not found. Is there anything gwt-test-utils does differently which means I need to specifically set the class path for it? Otherwise it should just work, since both gradle and eclipse know about all the relevant source folders and dependencies.

Categories

Resources