I'm trying to add a WADL method to my Spring Web Service application. I'm following the instructions on a number of pages/posts on the topic here and other help sites on the net.
However, my app keeps failing on the auto wire of the RequestMappingHandlerMapping.
The error is:
Error creating bean with name 'wadlController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping net.my.app.ws.thing.WadlController.handlerMapping; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] 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)}
I've done everything I can think of and search out even added:
mvc:annotation-driven
But the app was entirely annotation drive already, so that didn't seem right.
What else could I be missing? Is it a problem with Spring 3.1.1?
Here is the code for the top section of my controller. I did get it working by auto-wiring the ApplicationContext. However, I don't really like that solution.
package net.stuff.stuff.stuff;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import net.stuff.wadl.*;
#Controller
#RequestMapping("/application.wadl")
public class WadlController {
private static final Logger log = Logger.getLogger(WadlController.class);
#Autowired
private ApplicationContext ctx;
#RequestMapping(method = RequestMethod.GET, produces = { "application/xml" })
public #ResponseBody WadlApplication generateWadl(HttpServletRequest request) {
RequestMappingHandlerMapping handlerMapping = ctx.getBean(RequestMappingHandlerMapping.class);
WadlApplication result = new WadlApplication();
WadlDoc doc = new WadlDoc();
doc.setTitle("REST Service WADL");
result.getDoc().add(doc);
WadlResources wadResources = new WadlResources();
wadResources.setBase(getBaseUrl(request));
if (handlerMapping == null) {
log.error("handlerMapping is null in WadlController???");
return null;
}
Related
I created a test code for #RestController on the spring boot and this error occurs.
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
---------------------------------------------------------------------------
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'memberController' defined in file [C:\dev\react\Kculter\target\classes\com\prac\react\controller\MemberController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.prac.react.service.MemberService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
--------------------------------------------------------------------------------------------------
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.prac.react.service.MemberService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I see this problem even though I added #Service annotations to the MemberService class and #RestController annotations to the MemberController class.
How can I solve it?
I'll show my Test code, MemberCotroller, MemberService code below
MemberControllerTest.java
package com.prac.react.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.prac.react.model.dto.Member;
import com.prac.react.service.MemberServiceTest;
#WebMvcTest(MemberController.class)
public class MemberControllerTest {
#Autowired
MockMvc mvc; // 가상의 http request를 테스트 할때 만들기 위해서 사용하는 인스턴스
#Autowired
ObjectMapper obm;
Logger logger = LoggerFactory.getLogger(MemberServiceTest.class);
#Test
#DisplayName("로그인 테스트 1 ") // 회원이 존재할때를 가장했을때를 위한 테스트 코드
void testSignInMember() throws Exception {
// given
Member mb = new Member(1, "hankgood95#gmail.com", "이욱재", true);
String requestBody = obm.writeValueAsString(mb);
mvc.perform(post("/member")
.content(requestBody)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()) //status가 200이고
.andExpect(content().string(".com")) //content안에 .com이 있다면
.andDo(print()); //요청받은것들으 print 해라
}
}
MemberController.java
package com.prac.react.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.prac.react.model.dto.Member;
import com.prac.react.service.MemberService;
/* 이파일은 회원가입,로그인,회원정보수정 등등
회원 정보와 관련된 일을 할때 들어올 Controller 입니다 */
#RestController
public class MemberController {
//로그를 찍어보기 위해서 만든 인스턴스
Logger logger = LoggerFactory.getLogger(MemberController.class);
//MemberService 의존성 주입을 위해 사용할 인스턴스
MemberService ms;
public MemberController(MemberService ms){
this.ms = ms; //의존성 주입
}
#PostMapping("member")
public Member SignInMember(#RequestBody Member member){
if(ms.checkMember(member.getEmail()) > 0){ //이미 우리 회원일때 접근
//이미 우리 회원이라면 여기서 얻은 Member 정보를 가지고 메인페이지로 이동을 해야한다.
member.setCheckMember(true);
return member;
}else{//처음 가입할때 접근
//우리 회원이 아니라면 이제 회원가입 페이지로 이동을 해야한다.
member.setCheckMember(false);
return member;
}
}
}
MemberService.java
package com.prac.react.service;
import org.springframework.stereotype.Service;
import com.prac.react.model.dao.MemberDao;
#Service
public class MemberService {
MemberDao md;
//MemberDao 인스턴스의 의존성 주입을 위해 생성자 안에서 집어 넣어주었습니다.
//여기서 주의해야할점은 의존성 주입이 하나 이상일땐 #Autowired 어노테이션을 꼭 넣어줘야만 합니다.
public MemberService(MemberDao md){
this.md = md;
}
public int checkMember(String email){
return md.checkMember(email);
}
}
When you using the test slice #WebMvcTest:
Regular #Component and #ConfigurationProperties beans are not scanned when the #WebMvcTest annotation is used.
This means your class annotated with #Service is also not configured.
You can use #MockBean to create a mock for this service.
Reference with Example: Spring Boot Reference
Main Class
package com.prac.sdp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.prac.sdp.pdf.PdfGenerator;
#SpringBootApplication
public class SdpApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(SdpApplication.class, args);
PdfGenerator pdg=ctx.getBean(PdfGenerator.class);
pdg.pdfgenerate();
}
}
PdfGenerator.java
package com.prac.sdp.pdf;
import java.io.FileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
#Component
public class PdfGenerator {
#Autowired
PdfWriter writer; <------ Autowiring is not working here I don't know why.
}
Issue -- Consider defining a bean of type 'com.itextpdf.kernel.pdf.PdfWriter' in your
configuration.
Resolution tried:
Used #ComponentScan("com.itextpdf") --> Started getting Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
'com.prac.sdp.pdf.PdfGenerator' available.
Let me know how this issue can be fixed I am stuck at this. Thanks in advance.
create bean with #Bean annotation tag , as this is from third party library , you need to define by Method.
#Bean
public PdfWriter writer(){
return new PdfWriter();
}
Add above method to your SdpApplication class.
I have a weird issue of #Autowire failing as the following:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'EventTargetRepositoryTest': Unsatisfied dependency expressed through field 'eventTargetRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'EventTargetRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Funnily enough, this happens only on my test which uses the exactly same #Configuration.
#Service beans autowire perfectly in the actual application.
#Repository beans autowire perfectly in the actual application.
#Service beans autowire perfectly(??) in the JUnit Test.
#Repository beans fail to autowire in the JUnit Test.
Code is as follows(package structure omitted):
Test(which fails)
import CoreConfig
import EventTarget
import org.junit.Test
import org.junit.runner.RunWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringRunner
#RunWith(SpringRunner::class)
#ContextConfiguration(classes = [CoreConfig::class])
class EventTargetRepositoryTest {
private val LOGGER: Logger = LoggerFactory.getLogger(EventTargetRepositoryTest::class.java)
#Autowired //not autowiring for some reason. needs fixing.
private lateinit var eventTargetRepository: EventTargetRepository
#Test
fun selectOne() {
var eventTarget = EventTarget()
eventTarget.id = 1
eventTargetRepository.selectOne(eventTarget)
LOGGER.info(eventTarget.userId)
}
}
Application(which runs fine, along with working repository)
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
import org.springframework.boot.runApplication
#SpringBootApplication(scanBasePackages = ["com.omittedParentName"], exclude = [DataSourceAutoConfiguration::class])
class FrontendApplication
fun main(args: Array<String>) {
runApplication<FrontendApplication>()
}
Config(which the Test and Application both use)
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.FilterType
import org.springframework.context.annotation.PropertySource
import org.springframework.stereotype.Component
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
#ComponentScan(basePackages = ["com.omittedParentName"], useDefaultFilters = false,
includeFilters = [
ComponentScan.Filter(type = FilterType.ANNOTATION, value = [Service::class]),
ComponentScan.Filter(type = FilterType.ANNOTATION, value = [Component::class]),
ComponentScan.Filter(type = FilterType.ANNOTATION, value = [Repository::class]),
ComponentScan.Filter(type = FilterType.ANNOTATION, value = [Configuration::class])
])
#Configuration
#PropertySource("classpath:properties/core.properties")
class CoreConfig
repository
import EventTarget
import org.apache.ibatis.annotations.Mapper
import org.springframework.stereotype.Repository
#Mapper
#Repository
interface EventTargetRepository {
fun selectOne(eventTarget: EventTarget): EventTarget
}
mapper xml is irrelevant, so it's omitted.
As we can clearly see, the Test and Application literally use the same #Configuration. Aside from the fact that making all tests require applicationContext is bad structure, the test should work. Other beans like #Service work in the same tests, too.
Any help would be appreciated.
Please refrain from marking as duplicate unless it's a question of #Autowire failing only exclusively on #Repository for only on #Test yet working in release.
i am writing a junit test that have to invoke some method from some autowired dependency which has to interact with Cassandra, but i am getting this exception:
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.21 s <<< FAILURE! - in unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests
[ERROR] testFindByUsername(unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests) Time elapsed: 0.001 s <<< ERROR!
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'unicon.matthews.admin.service.repository.AdminUserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'unicon.matthews.admin.service.repository.AdminUserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
This is the junit test:
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.util.Version;
import org.springframework.test.context.junit4.SpringRunner;
import example.springdata.cassandra.util.CassandraKeyspace;
import unicon.matthews.admin.AdminUser;
import unicon.matthews.admin.service.repository.AdminUserRepository;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = CassandraConfiguration.class)
public class AdminUserRepositoryTests {
#ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost().atLeast(Version.parse("3.0"));
#Autowired AdminUserRepository repository;
#Before
public void setUp() throws Exception {
repository.deleteAll();
}
#Test
public void testFindByUsername() {
try {
final String userName = "aironman";
AdminUser.Builder myBuilderAdmin = AdminUser.Builder.class.newInstance();
myBuilderAdmin.withId("id");
myBuilderAdmin.withEmailAddress("some#domain.com");
myBuilderAdmin.withOrgId("orgId");
myBuilderAdmin.withPassword("some-password");
myBuilderAdmin.withSuperAdmin(Boolean.TRUE);
myBuilderAdmin.withTenantId("tenantId");
myBuilderAdmin.withUserName(userName);
//que viene aqui exactamente?
Map<String, String> someMetadata = new HashMap<String, String>();
someMetadata.put("some-key","some-value");
myBuilderAdmin.withMetadata(someMetadata);
AdminUser myAdminUser = myBuilderAdmin.build();
repository.save(myAdminUser);
Optional<AdminUser> loadedUserName = repository.findByUsername(userName);
assertNotNull(loadedUserName);
// assertThat(repository.findOne(homer.id).isPresent(), is(true));
assertEquals("something went wrong!",userName,loadedUserName.get().getUsername());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Done testFindByUsername!");
}
}
AdminUserRepository looks like:
import java.util.Optional;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import unicon.matthews.admin.AdminUser;
#Repository
public interface AdminUserRepository extends CrudRepository<AdminUser, String> {
#Query("select * from AdminUser where username = ?0")
Optional<AdminUser> findByUsername(final String userName);
}
CassandraConfiguration looks like:
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
#Configuration
#EnableAutoConfiguration
class CassandraConfiguration {
#Configuration
#EnableCassandraRepositories
static class CassandraConfig extends AbstractCassandraConfiguration {
#Override
public String getKeyspaceName() {
return "example";
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE;
}
}
}
I understand that spring is trying to instantiate this AdminUserRepository class which is created using CrudRepository from spring-data project. It is supposed that if i mark this interface with #Repository, spring will instantiate the class within the spring context in order that another bean will be capable to autowire it within it, so, why spring is not able to instantiate the dependency?
AdminUserRepository interface is located within src/main/java and AdminUserRepositoryTests is located within src/test/java.
this is my actual pom.xml, please help.
Marking a Spring data repository with #Repository actually doesn't do anything. If you wan't to enable a CrudRepository you need to annotate your configuration with #EnableJpaRepositories. However, since you are using Cassandra I think it's more likely you want to be using a CassandraRepository ?
public interface AdminUserRepository extends CassandraRepository<AdminUser, String> {
#Query("select * from AdminUser where username = ?0")
Optional<AdminUser> findByUsername(final String userName);
}
I use javax standard annotation #Named for defining beans in spring4. To set the bean name I could tried #Named("MyBean") but it did not change the bean name.
I used spring Component annotation #Component("MyBean") and it worked fine.
Is it possible to set the bean name by using #Named
The bean is defined asL
#Named("myBean") //This not
#Component("myBean") //This works
#Scope("session")
public class User implements HttpSessionBindingListener, Serializable {
The application.context is
<context:component-scan base-package="foo.bar" />
I agree to what #fabian has said. You can use #Named annotation to set the bean name. If bean name doesn't matches, it falls back to auto-wiring by type.
I tried couple of examples. They worked for me.
AppConfig.java
package com.named;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan
public class AppConfig {
}
NamedService.java
package com.named;
import javax.inject.Named;
#Named("namedTestDependency")
public class NamedService {
public void namedMethod(){
System.out.println("Named method");
}
}
NamedServiceTest.java
package com.named;
import static org.junit.Assert.assertNotNull;
import com.named.AppConfig;
import com.named.NamedService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=AppConfig.class)
public class NamedServiceTest {
//Matched by name of dependency
#Autowired
private NamedService namedTestDependency;
//Falls back to auto-wiring by type
#Autowired
private NamedService noDeclaration;
#Test
public void testAutowiring(){
assertNotNull(namedTestDependency);
assertNotNull(noDeclaration);
}
}