unable to autowire custom spring boot library project to my application - java

Importing custom spring-boot library jar to my application, and autowiring show the following error when I run the application
Parameter 0 of constructor in com.dilla.de.orca.addresssvc.service.TestScheduler required a bean of type 'com.dilla.de.orca.flowersvc.service.FlowerServiceImpl' that could not be found.
The Library module has following packages
Configuration
FlowerServiceConfiguration - create beans for Jaxb2Marshaller, WebServiceTemplate,
webserviceMessageSender
Model
Service
FlowerService (an interface no annotation)
FlowerServiceImp implements the interface and calls FlowerAdapter
FlowerAdapter (call external webservice)
Src/main/resources
Application.properties define external webservice url, and related properties
FlowerSvcLibApplication.java
public static void main(final String[] args) {
SpringApplication.run(FlowerSvcLibApplication.class, args);
}
I was autowiring the Flower Service interface as follows, in my application to test functionality
of library jar
#Component
public class MyFlowerService {
private FlowerService service;
#Autowired
public MyFlowerService(final FlowerService service) {
this.service = service;
}
I got the error I posted earlier. I did do more research, and one suggestion was creating “own auto-configuration”, but I still did not understand. How do I create autoConfiguration class to handle to autowire my library class, and also how does client using my library provide application property values. Currently, I hard coded actual values for example a webservice url, and now client can change this to be test or prod, and to do that how does my library module setup should be?

Please check #ComponenetScan & make sure that it has package path something like this “com.dilla.de.orca”

Related

#ComponentScan doesn't work in my Minecraft plugin

I am creating a plugin for Minecraft server in which I use this SpringFramework. And I use JavaConfig + Annotations, but my project couldn't normally in runtime due to #ComponentScan.I discovered the fact that this is only in the Minecraft server plugin, but I could be wrong. Although in a normal Spring project everything is scanned normally
I have a directory like this: me.stordshally.testplugin
Main class (me.stordshally.testplugin.Main)
public class Main extends JavaPlugin {
private User user;
#Override
public void onEnable() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
user = context.getBean(FacebookUser.class);
}
}
JavaConfig (me.stordshally.testplugin.SpringConfig)
#Configuration
#ComponentScan
public class SpringConfig {
}
Component (me.stordshally.testplugin.FacebookUser) (exists also User interafce in that directory)
#Component
public class FacebookUser implements User {
#Override
public String getNet() {
return "Facebook";
}
}
And at the moment context.getBean I get this exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'me.stordshally.testplugin.FacebookUser' available
onEnable - starts when the server starts, consider it as an analog of psvm.
Why is this happening? How can I fix my ComponentScan?
Github for test: https://github.com/Prot-CN/SpringBug
Ideally, some more information would have helped, however, I do not know what the src package structure looks like but try explicitly providing base package like
#ComponentScan(basePackages = "me.stordshally.testplugin")
This tells spring explicitly where to look for potentials beans to create. Please make sure you provide the path under which all your beans are located.
If this doesn't work, it means for some reason your application is failing, try running your app in debug mode by setting log-level to debug. It will tell where the issue is. it's the best I can tell from the info provided, Hope this helps.

Spring Beans Created Multiple Times

I am just new to Spring and facing a design problem. The problem is i have a maven multiple module projects. Project Structures goes as follows.
module-backoffice - Packaging(war)
module-ws - Packaging(war)
module-dao - Packaging(jar)
module-shared - Packaging(jar)
In "module shared "all my service class and in "module-dao" all dao related codes exists.
module-shared and module-dao is in the build path of module-backoffice and module-ws.
Now Problem is when i run module-backoffice war and module-ws war Spring creates two instance of Service class beans and dao class beans.
What should i do so that one instance of service class and dao class will be created and shared among multiple war ? Please help. Thanks you.
Code in Module-Shared: Below is Service factory class
#org.springframework.stereotype.Service
public class Services {
#Autowired
private List<Service> services;
private static final Map<Class<?>, Service> serviceCache = new ConcurrentHashMap<Class<?>, Service>();
#PostConstruct
public void initServiceCache() {
services.forEach(service -> serviceCache.put(service.getClass(), service));
services = null;
}
public static Bootstrap bootstrap() {
return (Bootstrap) serviceCache.get(Bootstrap.class);
}
And the service class is :
#Component
public class Bootstrap implements Service {
public Bootstrap() {
System.out.println("Bootstrap");
}
}
When i run tomcat deploying two wars then in console two times "Bootstrap" printed. How do i restrict that.?
The purpose of web container like tomcat is to able to run applications independently so they can be started and stopped without affecting each other. In case you think there can be multiple future applications will also require the same service, you can make a separate application and expose an API for the operations.

Spring - Need to autowire #RestController class in a #Component class

I have combination of web and core projects under the same maven parent module as like,
Parent
- Web (com.parent.test.web)
- Core (com.parent.test.core)
I would like to refer the web module dependency in the core project to invoke some of the api from web module
Web project sample,
com.test.parent.web
public interface RestInterface {
public ResponseEntity load();
}
#RestController
public class RestInterfaceImpl implements RestInterface {
#Override
#RequestMapping(value = "/getData", method = RequestMethod.GET, produces = APPLICATION_JSON)
public #ResponseBody ResponseEntity<Object> load() {
}
}
Core project sample,
com.test.parent.core
#Component
public class CoreImpl implements CoreInterface {
// Is this possible to autowire
#Autowired
private RestInterface restInterface;
public boolean getOptions() {
ResponseEntity<Object> results = restInterface.load();
for (Object o : results) {
//TODO
}
}
}
Because the projects are developed within the same parent pom module. All the projects will be grouped into a springboot jar and will be deployed into the same environment. So, I'd like to refer the web project dependency into the core project and trying to scan the web classes inside the core project.
I'd like to get clarified on few things ,
Is it the good approach ?
If it is the good approach, how we can implement ?
If not then what will be correct approach ?
IMHO it is definitely not a correct approach. The separation of concerns principle says that controllers should only be small pieces of code that take parameters from the requests, pass them to business classes, and forward to a view that will display the results.
If you need to call some methods of the controller from a core class, it means but you have a Fat Ugly Controller carrying business methods inside it. The correct approach is to separate the web part => controller, from the business part => service layer.
That way you create a service bean that will be autowired in both the (now thin) controller and the other core classes that need to call its methods.

JerseyTest unsatisfied dependency (Dependency Injection)

I need to test my RESTful service and I thought the most appropriate way to do it would be using the Jersey Test Framework since I am already using Jersey for my service.
However, when running a simple test I am getting a UnsatisfiedDependencyException because the implementation of the DAO I am using in the service is not found (it's being set via DI). This error used to happen to me everytime I modified my pom.xml Maven configuration file, mostly when adding or removing dependencies. Supposedly, the IDE I'm using, IntelliJ IDEA is supposed to regenerate the artifacts automatically, but for me to avoid this dependency failure I needed to remove the old artifact from the Tomcat server deployment options as well as from the project structure, and add it again.
The problem here is that the test framework is using a separate server, as the documentation said. I am using the following one:
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.23.1</version>
</dependency>
I don't know how to solve the dependency issue if I am using a different server.
The top error message in the exception stack says:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no
object available for injection at SystemInjecteeImpl
Any ideas?
Edit. I managed to patch it with a dirty solution.
First, let me show you how I was injecting the DAO:
// Binder.java
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(TournamentDao.class).to(ITournamentDao.class).in(Singleton.class);
}
}
// DependencyInjectionFeature.java
#Provider
public class DependencyInjectionFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(new Binder());
return true;
}
}
// EventSchedulerService.java
#Path("eventscheduler")
public class EventSchedulerService {
private ITournamentDao dao;
#Inject
public EventSchedulerService(ITournamentDao tournamentDao) {
dao = tournamentDao;
}
}
The web configuration file web.xml scans the package where these classes are placed (the package has the same name than the one where the test exists) and perform the dependency injection since it finds the #Provider annotation.
To patch my issue I did the exact same thing in the test class:
public class EventSchedulerServiceTest extends JerseyTest {
protected Application configure() {
ResourceConfig config = new ResourceConfig(EventSchedulerService.class);
config.register(new AbstractBinder() {
#Override
protected void configure() {
bind(TournamentDao.class).to(ITournamentDao.class).in(Singleton.class);
}
});
return config;
}
}
Obviously this is a bad idea because now I have duplicate code; but it did the trick. I'd like to know how to make the test server to use the service configuration correctly.
I remember from a previous discussion in the comments here, you had the problem of not using a ResourceConfig to configure your main application. You we instead using web.xml.
The reason you are using a Feature annotated with #Provider is that you we're using package scanning in your web.xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>your.packages.to.scan</param-value>
</init-param>
The package scan picked up the #Provider on the Feature, and automatically registers it. This provider is what is used to register the Binder, which is what configured the dependency injection.
As mentioned, a Jersey application can be configured in a ResourceConfig or in a web.xml. Anything jersey configuration you can do in the web.xml, you can also do in the ResourceConfig. There are a bunch of different ways you can register components with the ResourceConfig
You can just call register
config.register(new DependencyInjectionFeature());
You can also package scan, the same way you are doing in the web.xml, by calling packages
config.packages("your.packages.to.scan");
You should also look at your implementation of the Binder class. It extends AbstractBinder. The look at how you are currently configuring the DI in the test
config.register(new AbstractBinder() {
#Override
protected void configure() {
...
}
});
You are registering an AbstractBinder instance. So you know that calling you can register the DI configuration calling register on the ResourceConfig, so you could instead of registering a different binder, just register an instance of the Binder class
config.register(new Binder());
So you have some options.

How to use #Service class from another Web App Project

I'm having a problem right now, I have two Dynamic Web App Project (ProjectA and ProjectB) and I need to reuse methods from Service class from ProjectA. Right now I'm developing ProjectB, the methods I need to reuse from ProjectA are pulling datas from its own database, and I need to have those data.
I've already done doing this following steps
Java Build Path -> Add Project
Project Reference -> Add Project
and I also tried to add ProjectA jar file as Maven dependency and still not working
In ProjectB, I can already import and call methods from ProjectA but I'm having a nullPointerException.
ProjectA.java
public interface CustomerService {
public Customer getCustomerDetails(Long id);
}
The above class is the class that I need to reuse, for to me have ProjectA data.
ProjectB.java
public class CustomerController {
private CustomerService customerService;//service from another project
public ModelAndView getCustomer(Long id){
Customer = this.customerService.getCustomerDetails(id);
}
}
Now, In ProjectB I need to call CustomerService.class and use its own method for me to have its own data. But unluckily I'm having a NullPointerException everytime call CustomerService interface
Please help I can't get the right thing to do.
Thanks in advance
Your problem is that you are not telling Spring to instantiate an object that implements CustomerService, for being injected in CustomerController. You can do:
Annotate the CustomerService implementation (CustomerServiceImpl in ProjectA??) with #Service, for tell Spring to instantiate that implementation.
Add jar of ProjectA in ProjectB
Tell Spring to scan for beans to instantiate, in xml configuration file: <context:component-scan base-package="base.package.in.project.a" />
Annotate customerService property in CustomerController with #Autowired for inject the instance of CustomerServiceImpl in spring context into this property.

Categories

Resources