rubio
rubio

Reputation: 966

Spring boot with external jar 'Not a Managed Type'

I have a spring application that is pulling in a commons jar. This jar has DTO classes with annotations. Running the mvn clean build command runs successfully and builds the jar. Once i run java -jar target/MyApp-1.0.0.BUILD-SNAPSHOT.jar i will get the below error.

I have opend the MyApp-1.0.0.BUILD-SNAPSHOT.jar and found all my classes inside that jar.

I have opened the jar that contains MyApplicationJobDTO inside my snapshot and verified the file is there.

It seems that at runtime java cannot find the class even though the class is there. I dont believe i should have to add anything to java class path since the jar is located inside of the snapshot jar. I am stuck and unsure of why i am getting runtime errors.

Caused by: java.lang.IllegalArgumentException: Not an managed type: class com...MyApplicationJobDTO

Class with its annotations

@Component
@Entity
public class MyApplicationJobDTO implements Serializable {

My command to run

mvn clean package && java -jar target/MyApp-1.0.0.BUILD-SNAPSHOT.jar 

My Main class

@EnableJpaRepositories
@ComponentScan
@EntityScan
@Configuration
@EnableAutoConfiguration
public class Application {
    public static void main(String[] args) {

        ApplicationContext context = 
                new ClassPathXmlApplicationContext("file:src/main/java/com/myapp/beans.xml");

        SpringApplication.run(Application.class, args);
    }
}

Beans.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"
    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/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

Error

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyApplicationJobController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myapp.xx.yy.models.MyApplicationJobDAO com.myapp.xx.yy.web.MyApplicationJobController.MyApplicationJobDAO; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyApplicationJobDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.myapp.aa.bb.myapptest.commons.dto.MyApplicationJobDTO
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at com.myapp.xx.yy.Application.main(Application.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myapp.xx.yy.models.MyApplicationJobDAO com.myapp.xx.yy.web.MyApplicationJobController.MyApplicationJobDAO; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyApplicationJobDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.myapp.aa.bb.myapptest.commons.dto.MyApplicationJobDTO
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:509)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290)
    ... 22 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyApplicationJobDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not an managed type: class com.myapp.aa.bb.myapptest.commons.dto.MyApplicationJobDTO
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1021)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:964)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:481)
    ... 24 common frames omitted
Caused by: java.lang.IllegalArgumentException: Not an managed type: class com.myapp.aa.bb.myapptest.commons.dto.MyApplicationJobDTO
    at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:219)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:149)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:88)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:68)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:158)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:224)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:210)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)

edit If i manually add all the classes in my external jar that need to be used in my spring project it works. I still cannot get the classes to load from an external jar

Upvotes: 7

Views: 9182

Answers (6)

dvtoever
dvtoever

Reputation: 3996

I gave the same answer here: https://stackoverflow.com/a/41145229/372838 but this question states more clearly the problem only occurs when running the spring boot application as a JAR


In my project we experienced a similar problem. When running with mvn spring-boot:start the @EntityScan works fine and can find all entities including those in libraries. When we run the springboot application using java -jar the application cannot find entities that are referenced via a maven dependency. It seems the classloading is different when the springboot application is run as a jar.

You can instruct spring-boot to 'unpack' the JAR dependency that contains the entities that can not be found. You can add the following section to your pom.xml:

<project>
  ...

  <build>
      <plugins>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
              <configuration>
                  <requiresUnpack>
                      <dependency>
                          <groupId>org.example.pkg.commons</groupId>
                          <artifactId>domain-jar</artifactId>
                      </dependency>
                  </requiresUnpack>
              </configuration>
          </plugin>
      </plugins>
  </build>

</project>

Upvotes: 5

Enrico Giurin
Enrico Giurin

Reputation: 2273

I had a similar issue, I sorted it out by adding this class:

@EntityScan(basePackages = { "com.internal.model", "com.external.model" })
@Configuration
public class ScanJPA {}

Make sure to include both the root packages of your JPA entities, that internal and that defined in the dependency, external jar.

Upvotes: 1

Ullas Hunka
Ullas Hunka

Reputation: 2211

I believe the answer is late, however, I had the same situation where my entities and repository are parked in the external jar file. After many tries, I found the solution by declaring @SpringBootApplication and @ComponentScan with the basePackage parameter.

@ComponentScan(basePackages = { "com.external.yourExternalPackage.*" })
@EnableJpaRepositories
@EntityScan(basePackages = { "com.external.model.foo.entity" })
@SpringBootApplication
@EnableConfigurationProperties
public class Application {
    public static void main(String[] args) {


    SpringApplication.run(Application.class, args);
  }
}

Thanks.

Upvotes: 1

ndjensen
ndjensen

Reputation: 139

Similar to dvtoever, I also added my answer to the linked question but will add it here in case it helps someone who comes across this in the future.


My project had a similar problem with a Spring Boot application. I had the @Entity class in the common jar at a package such as com.foo.jpa, then an application jar that depended on the common jar. The application jar had the main @SpringBootApplication class at a package such as com.foo.bar.appname. @EntityScan, @ComponentScan, and @EnableJpaRepositories did not detect the @Entity class and gave the "Not a managed type" error regardless of what package names I provided to the annotations.

I finally fixed it by renaming the package names. I put the @SpringBootApplicationapplication class at com.foo.bar and the @Entity class in the common jar at com.foo.bar.whatever. As long as the @Entity class in the common jar was at the same package or a subpackage of the @SpringBootApplication class, it was autodetected, regardless of which jar it was in.

Upvotes: 0

kuhajeyan
kuhajeyan

Reputation: 11017

Remove @EntityScan it is Deprecated. If you use the @EntityScan it will override @ComponentScan

or

you should specify the base package to scan for the JPA entities. @EntityScan("com.myapp.xx.yy.models")

Upvotes: 4

Reimeus
Reimeus

Reputation: 159754

Your application package is probably different from that of your DTO class so Spring can't find it. You could do

@ComponentScan("com.myapp.xx.yy.models")

Upvotes: 3

Related Questions