私は、SpringとHibernateを使ってエンティティ、サービス、そしてサービスのJUnitテストを作成することから私のプロジェクトを始めました。これらすべてがうまくいきます。それから、私はspring-mvcを追加してステップバイステップのチュートリアルを使ってこのWebアプリケーションを作成しましたが、@AutowiredアノテーションでControllerを作成しようとすると、配置中にGlassfishからエラーが発生します。どういうわけかSpringは私のサービスを見ていないと思いますが、多くの試みの後で私はまだそれを扱うことができません。
とのサービスのテスト
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
そして
@Autowired
MailManager mailManager;
正常に動作します。
@Autowiredのないコントローラでも、問題なくWebブラウザでプロジェクトを開くことができます。
/src/main/resources/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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://Java.Sun.com/xml/ns/persistence/orm http://Java.Sun.com/xml/ns/persistence/orm_2_0.xsd">
<context:property-placeholder location="jdbc.properties" />
<context:component-scan base-package="pl.com.radzikowski.webmail">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!--<context:component-scan base-package="pl.com.radzikowski.webmail.service" />-->
<bean id="dataSource" class="org.Apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- Persistance Unit Manager for persistance options managing -->
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<!-- Entity Manager Factory for creating/updating DB schema based on persistence files and entity classes -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="persistenceUnitName" value="WebMailPU"/>
</bean>
<!-- Hibernate Session Factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--<property name="schemaUpdate" value="true" />-->
<property name="packagesToScan" value="pl.com.radzikowski.webmail.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<!-- Hibernate Transaction Manager -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Activates annotation based transaction management -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
/webapp/WEB-INF/web.xml
<web-app xmlns="http://Java.Sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="WebApp_ID" version="2.4" xsi:schemaLocation="http://Java.Sun.com/xml/ns/j2ee http://Java.Sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
/webapp/WEB-INF/mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
pl.com.radzikowski.webmail.service.AbstractManager
package pl.com.radzikowski.webmail.service;
import org.Apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Master Manager class providing basic fields for services.
* @author Maciej Radzikowski <[email protected]>
*/
public class AbstractManager {
@Autowired
protected SessionFactory sessionFactory;
protected final Logger logger = Logger.getLogger(this.getClass());
}
pl.com.radzikowski.webmail.service.MailManager
package pl.com.radzikowski.webmail.service;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@Transactional
public class MailManager extends AbstractManager {
// some methods...
}
pl.com.radzikowski.webmail.HomeController
package pl.com.radzikowski.webmail.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import pl.com.radzikowski.webmail.service.MailManager;
@Controller
@RequestMapping("/")
public class HomeController {
@Autowired
public MailManager mailManager;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String homepage(ModelMap model) {
return "homepage";
}
}
エラー:
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /WebMail
SEVERE: Exception while loading the app : Java.lang.IllegalStateException: ContainerBase.addChild: start: org.Apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.com.radzikowski.webmail.service.MailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.com.radzikowski.webmail.service.MailManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
たくさんのコードですみませんが、私はもうそのエラーの原因となるものを知りません。
追加
私はインターフェイスを作成しました:
@Component
public interface IMailManager {
追加された道具:
@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {
そしてautowiredを変更しました:
@Autowired
public IMailManager mailManager;
しかし、それでもエラーが発生します(@Qualifierを試したときにも)
..フィールドを自動配線できませんでした:public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
@Componentと@Transactionalのさまざまな組み合わせで試してみました。
どういうわけか、beans.xmlをweb.xmlに含めるべきではありませんか?
あなたはクラスAbstractManager
の代わりにインタフェースMailManager
を自動配線するべきです。 AbstractManager
の実装が異なる場合は、@Component("mailService")
を記述してから@Autowired @Qualifier("mailService")
の組み合わせを記述して、特定のクラスを自動配線できます。
これは、Springがインタフェースに基づいてプロキシオブジェクトを作成して使用するためです。
私のテストが私のコンポーネントと同じパッケージに入っていなかったので、私はこれが起こりました。 (私のコンポーネントパッケージの名前は変更しましたが、テストパッケージの名前は変更していませんでした。)そして私のテスト@ComponentScan
クラスで@Configuration
を使用していたので、私のテストはそれらが依存するコンポーネントを見つけられませんでした。
ですから、このエラーが発生した場合は、もう一度確認してください。
重要なのは、サーバーの起動時にアプリケーションコンテキストとWebアプリケーションコンテキストの両方がWebApplicationContextに登録されるということです。テストを実行するときは、どのコンテキストをロードするかを明示的に指示する必要があります。
これを試して:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
これで私の時間の大部分を費やした!私の悪い!後で私がアノテーションService
またはComponent
を宣言したクラスは抽象型であることがわかりました。 Springframeworkでデバッグログを有効にしていましたが、ヒントは得られませんでした。抽象型の場合はクラスをチェックしてください。その場合、適用される基本的な規則は抽象クラスをインスタンス化できません。
Maxが示唆しているように、正しい方法はAbstractManagerを自動配線することですが、これもうまくいくはずです。
@Autowired
@Qualifier(value="mailService")
public MailManager mailManager;
そして
@Component("mailService")
@Transactional
public class MailManager extends AbstractManager {
}
具体的な実装だけに@Component
を付けて試してみることはできますか?次の 答え が役に立つかもしれません。それは似たような問題です。私は通常Springアノテーションを実装クラスに入れます。
私は最近これに遭遇しました、そして結局のところ、私は私のサービスクラスに間違ったアノテーションをインポートしました。 Netbeansにはimport文を隠すオプションがあるので、しばらくの間それを見ませんでした。
私は@org.jvnet.hk2.annotations.Service
の代わりに@org.springframework.stereotype.Service
を使いました。
私のjarファイルの1つからクラスを自動配線している間、私は同じ問題に直面していました。 @Lazyアノテーションを使用して問題を修正しました。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
@Autowired
@Lazy
private IGalaxyCommand iGalaxyCommand;
これはあなたを助けるかもしれません:
私のプロジェクトでも同じ例外があります。 @Autowiredにしたいインターフェースを実装しているクラスへの@Serviceアノテーションが欠けていることに気付きながら検索しました。
あなたのコードでは、MailManagerクラスに@Serviceアノテーションを追加することができます。
@Transactional
@Service
public class MailManager extends AbstractManager implements IMailManager {
もっと見る
http://www.baeldung.com/spring-nosuchbeandefinitionexception
私の推測はここにある
<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
すべての注釈は最初にuse-default-filters = "false"によって無効にされ、その後@Controller注釈のみが有効にされます。したがって、@ Componentアノテーションは有効になっていません。
@Autowire MailManager mailManagerの代わりに、以下のようにBeanをモックすることができます。
import org.springframework.boot.test.mock.mockito.MockBean;
::
::
@MockBean MailManager mailManager;
また、@MockBean MailManager mailManager;
クラスで@SpringBootConfiguration
を個別に設定し、以下のように初期化することもできます。
@Autowire MailManager mailManager
コントローラをテストしているならば。テストクラスで@WebAppConfigurationを使用することを忘れないでください。
これは、サービスクラスに自動配線された依存関係を追加しましたが、サービスユニットテストでそれを注入されたモックに追加するのを忘れたためです。
ユニットテスト例外は、問題が実際にユニットテストにあったときにサービスクラスの問題を報告するように見えました。振り返ってみると、エラーメッセージは正確に何が問題なのかを私に言った。
<context:component-scan base-package="com.*" />
同じ問題が到着したので、アノテーションをそのままにしてディスパッチャサーブレット::ベースパッケージのスキャンをcom.*.
として保存することで解決しました。