While Trying to autowire a service class to my restcontroller in springboot, it is throwing build error unexpected token #, at #Autowired notation
This is my controller class.
#RestController
class RestAPIController{
#Autowired
private getTextBooks service
#RequestMapping(value = "/textbooks", method = RequestMethod.GET)
Interface for autowiring
import org.springframework.stereotype.Component
#Component
public interface Books{
public String getText(String name)
}
Class implementing Interface
#Componet
Class getTextBooks implements Books{
#Override
def getText(String name){
return "Text Book Name is" + name
}
}
Unable to Autowire in Controller
Name your class in capital letter like :
#Componet
Class GetTextBooks implements Books{
#Override
def getText(String name){
return "Text Book Name is" + name
}
}
It's java convention to name class by starting with Capital case letters.
Related
I have a controller class which further calls service class method. An AOP #Before aspect is applied on the service class method.
package com.example;
#RestController
public class BookController {
#Autowired
BookService bookService;
#RequestMapping(value = "/getBookDetails", method = RequestMethod.GET,
#RequestBody BookRequest bookRequest))
public String processBookDetails() {
System.out.println("Inside controller class");
String details = bookService.getBookDetailsInfo(bookRequest,bookName);
}
}
Service class
package com.example;
#Service
public class BookServiceImpl implements BookService {
#Override
public String getBookDetailsInfo(BookRequest bookRequest,String bookName) {
//some code
// call getBookDEtails
getBookDetails(bookInfoObj)
returns "Book details";
}
#CallBookInfo-- custom annotation for aspect which needs to be executed before getBookDetails is called
getBookDetails(BookInfoObj obj){
}
An aspect is written to be executed #Before the method getBookDetails() of BookServiceImpl
//Custom annotation
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CallBookInfo{}
//Aspect
#Aspect
#Configuration
public class BookAspect {
#Before("#annotation(com.example.CallBookInfo)")
public Object beforeBookAdvice(JoinPoint joinpoint) {
System.out.println("Start aspect");
Object result= null;
try {
BookRequest obj= joinpoint.getArgs();
System.out.println("End aspect");
}
catch(Exception e) {}
return result;
}
}
Execution goes as below,
Controller calls BookServiceImpl.getDetailsInfo() method.
getBookDetails() is called inside this method after some conditions
#Before Aspect is called before the getBookDetails() due to the custom
annotation #CallBookInfo
How to get the BookRequest object which was passed from the Controller class to the service class and after some processing return it back to the service class from the aspect
Thank you in advance !!
Here is my AppConfig:
#Configuration
#EnableWebMvc
#ComponentScan
class AppConfig{
#Bean("myname")
fun name(): Name = Name("Quang")
}
Data class:
data class Name(val value: String ="")
My Controller Class:
#Controller
#RequestMapping("/")
class Main{
#RequestMapping("/")
#ResponseBody
fun index(#Autowired #Qualifier("myname") name: Name): Name {
//this return ""
return name
}
}
The result is "" instead of "Quang".
But now if I inject it from field like this, it works fine:
#Controller
#RequestMapping("/")
class Main{
#Autowired(required = true)
#Qualifier("myname")
lateinit var name:Name
#RequestMapping("/")
#ResponseBody
fun index(): Name {
//this return "Quang" as expected
return name
}
}
So can you explain why #Autowired doesn't works when I use it in method parameter
According to documentation:
Marks a constructor, field, setter method or config method as to be
autowired by Spring's dependency injection facilities.
In your first example, Spring will not autowire anything.
I'm trying to autowire a service in my rest controller like these:
rest controller:
#ApplicationPath("/greetings")
#Component(immediate = true, service = Application.class)
public class RestControllerApplication extends Application {
#Autowired
private MyService myService;
public Set<Object> getSingletons() {
return Collections.<Object>singleton(this);
}
#POST
#Path("/getUploadType")
#Produces("application/json")
public JsonObject getUploadType() {
...
myService.findUploadTypes();
...
}
}
service:
#Component
public class UploadService {
private static final Logger log = Logger.getLogger(UploadService.class);
#Autowired
private OneDAO oneDAO;
#Autowired
private TwoDAO twoDAO;
...
}
but in my rest controller, uploade service is null. Why?
Spring uses its own set of annotations. Instead of #Path plus #[HTTP method] you should use #RequestMapping.
You can find an example here
There is also an extended example here
I have got access to my bean, with these few line of code:
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyService myService = context.getBean(MyService.class);
You are declaring a UploadService as #Component but trying to autowire a MyService instance in your controller...
There are two options: you can declare correct service type in your controller or you can make UploadService inheriting from MyService.
Here is a sample class below
#Service("testService")
public class TestService {
public String something() {
return "abc";
}
}
I want to extend the class and let the container know that it needs to pick up my extended class from now.
#Service("extendedTestService")
public class ExtendedTestServiceMock extends TestService {
#override
public String something() {
return "xyz";
}
}
Test class
public class TestClass extends SpringTest {
#Autowired
#Qualifier("extendedTestService")
private ExtendedTestServiceMock testService;
public void testMethod(){
......
}
}
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [TestService] is defined: expected single matching bean but found 2: ExtendedTestServiceMock,testService
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
... 91 common frames omitted
How to resolve it?
You haven't defined a bean of type ExtendedTestService.
You have only defined a bean of type ExtendedTestServiceMock.
Try this:
#Autowired
#Qualifier("extendedTestService")
private TestService testService;
The solution is use a #service anotation, you should inject the service like this:
#Autowired
private TestService testService;
And then you can use the methods of TestService
I have a scenario wherein my ServiceImpl and Business Class implements the same interface. But im unable to autowire both of them.
#RestController
#RequestMapping("/myservice")
public interface myInterface{
#RequestMapping(value="/getSomething/{input}", method=RequestMethod.GET)
doSomething(String input);
}
Now i have two classes which implements same interface
#Component
#Qualifier("doSomethingImpl")
public class DoSomethingImpl implements myInterface{
#Autowired
#Qualifier("businessLayer")
myInterface businessLayer;
doSomething(#PathVariable String input){
//my logic here
}
}
#Component
#Qualifier("businessLayer")
public class BusinessLayer implements myInterface{
doSomething(#PathVariable String input){
//my logic here
}
}
Now when i run it on server i'm getting following error
Cannot map handler 'DoSomethingImpl' to URL path
[/myservice/getSomething/{input}]: There is already handler of type
[class com.mypackage.business.BusinessLayer] mapped.
Could someone please help me to resolve this error
The problem is that both controllers are being mapped to the same path. I suggest you change your code to something like:
public interface myInterface{
#RequestMapping(value="/getSomething/{input}", method=RequestMethod.GET)
public Whatever doSomething(String input) {
//whatever
}
}
#RequestMapping("something")
#RestController
public class DoSomethingImpl implements myInterface{
}
#RequestMapping("somethingElse")
#RestController
public class BusinessLayer implements myInterface{
}