简体   繁体   中英

Autowiring a Spring 3.1 standalone application returning “No unique bean of type [x.x.x.x] is defined” exception

I am writing a standalone application (not web based) which will be run from the command prompt using the command:

java -jar myapplication.jar 

I developed the application on eclipse as a Maven project so Eclipse retrieves all the dependant libraries. If i right click the main class and select "Run As ">"Java Application" it works fine.

Now the problem I have is I need to deploy the application as a single jar file. To do this, I used Eclipse to export the application as a "Runnable Jar" (ie via the "export command"). This generated the jar file. I looked into the jar file and all the classes and the dependent jar files are in the jar file. The Spring application context file is also in the jar file in the top level folder. The "inside" of the jar file looks like this:

- com
    - myapp
      - service
         - MyAppService.class
      - dao
         - MyAppDataDao.class   
      - MyMainClass.class


- META-INF
- org
- application-context-components.xml
- log4j.properties
- [several jar files for spring, log4j, velocity etc)

I tried running the jar file using the following command and it gave me this error:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.myapp.MyMainClass] is defined: expected single bean but found 0:
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:257)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1012)
        at com.myapp.MyMainClass.init(MyMainClass.java:44)
        at com.myapp.MyMainClass.main(MyMainClass.java:65)
        ... 5 more

The file com.myapp.MyMainClass is in the jar file with the correct name. The classes in the package are autowired. I think that i must have missed something in the annotations or maybe something in the application context file. The structure of the classes and the annotations used is shown below:

MyMainClass

@Component
public class MyMainClass{

    @Autowired
    MyAppService myAppService;

    public static void main(String args[]){
        try{
            context = new     ClassPathXmlApplicationContext(properties.get("app.context"));

 MyMainClass mymainClass = context.getBean(MyMainClass.class);
 mymainClass.myAppService.getData()....
 ....
            }catch(Exception e){
                throw new CWAException(fname + ":" + e);
            }
        }
    }

The app.context property returns the name of the application context file.

MyAppService

@Service
public class MyAppService{

    @Autowired
    MyAppDataDao myAppDataDao;

    ---
    ---
    ---
}

MyAppDataDao

@Repository("myAppDataDao;")
public class MyAppDataDao {

    getData(){
    }

    ---
    ---
    ---
}

The application context file looks like this

<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"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- Auto scan the components -->
    <context:component-scan base-package="com.myapp" />

    <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean" 
          p:resourceLoaderPath="file://C:\template" 
          p:preferFileSystemAccess="true"/>  

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
        <property name="url"><value>jdbc:oracle:thin:@x.x.x.x:x</value></property>
        <property name="username"><value>xxx</value></property>
        <property name="password"><value>xxx</value></property>
    </bean>              
</beans>

Looking at the error I would guess that the Autowiring is not kicking in but I cant figure out where in the configuration I got it wrong. The application is in the packaged jar file and I am loading the file using ClassPathXmlApplicationContext so it should find it. I also don't understand why it works on eclipse but not after it has been exported.

Any ideas?

The class PathMatchingResourcePatternResolver in Spring3.0 atleast does not search for the classes marked with autowiring annotation inside jars.

Add the directory in which the jar is present to the classpath.

It will detect the classes and load as beans.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM