#Inject not working in Singleton but works in API classes - java

I'm setting up authentication in my Jetty API. And I wanted to use dependency injection to inject a class with database functions into the class that checks the provided token against the database.
I've already used dependency injection in my API classes like this:
#Path("/account")
#Api(value = "/account", description = "Web Service for accounts")
public class AccountService {
#Inject
private IAccountRepo accountRepo;
}
To make this work I created a class which binds the actual class to the interface.
public class RepositoryBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MovieRepo.class).to(IMovieRepo.class);
bind(AccountRepo.class).to(IAccountRepo.class);
}
}
I registered it like this:
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.packages(
MovieService.class.getPackage().getName(),
AccountService.class.getPackage().getName(),
ApiListingResource.class.getPackage().getName()
);
resourceConfig.register(new RepositoryBinder());
resourceConfig.register(new AuthenticationFilter());
resourceConfig.register(ObjectMapperContextResolver.class);
But when I try to use it in my TokenValidator class, the accountRepo is always null.
My TokenValidator looks like this:
#Singleton
public class TokenValidator implements ITokenValidator {
#Inject
private IAccountRepo accountRepo;
private static ITokenValidator instance = null;
private TokenValidator() {
}
public static ITokenValidator getInstance() {
if (instance == null) {
instance = new TokenValidator();
}
return instance;
}
//Some token validation logic here
}
I expected the #Inject to work right away but it doesn't. I've allready tried a bunch of things like registering the TokenValidator the same way the API classes are registered but nothing worked so far.

Related

Springboot cannot find my autowired bean despite all scanning

So I have a class called ClientFactory that I import into my project using a jar. It looks like this:
#Component
public class ClientFactory {
#Autowired
private Client client;
public ClientFactory() {
}
public Client get() {
return this.client;
}
}
and my class that uses this looks like:
#SpringBootApplication(scanBasePackages = {"path.to.client.*"})
#EnableAutoConfiguration
public class ProjectClient {
#Autowired
public ClientFactory clientFactory;
public ProjectClient() {}
public String getSomething(String something){
Client client = (Client) clientFactory.get();
return "x";
}
}
And I call this piece of code from my test class:
#SpringBootTest
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#Disabled
#TestPropertySource(properties = { //
"some.property=value", //
})
public class SomeTests {
#Autowired
ProjectClient p;
#Test
public void sampleTest() throws Exception {
p.getSomething("sample");
}
}
and I get the following error:
Field clientFactory in ProjectClient required a bean of type 'ClientFactory' that could not be found.
Action:
Consider defining a bean of type 'ClientFactory' in your configuration.
I've tried all combinations of Entity, Component and Package scans but nothing seems to be working. The application simply cannot find that bean, I've googled high and low and can't seem to find a way to get this working - I'm new to Spring boot - please help :(
I believe this class isn't compiling properly.
#Component
public class ClientFactory {
#Autowired
private Client client;
public Factory() {
}
public Client get() {
return this.client;
}
}
While Class name is ClientFactory the constructor been defined as Factory, which isn't possible for compiler to compile it.
Would you please change Factory to ClientFactory (OR Remove default constructor If you don't have specific use) and try again
Create clientfactory with bean annotation since you are referring clientFactory by importing from jar
#Bean
public Clientfactory clientfactory () {
return new Clientfactory ();
}
It took me too long but I figured it out. I made a change to ProjectClient as follows:
#Service
#ComponentScan(basePackages = {"path.to.*"})
public class ProjectClient {
I'm guessing my path to client was incorrect or undetectable (I used the same path for importing that class).
Looks like you have forgotten to add #RunWith(SpringRunner.class) on your test class.

Spring Boot: how to inject dependencies into a class called by a library?

I'm using Kinesis Client Library (KCL) and Spring boot. To use KCL, I have to implement a class (I named it RecordProcessor) for interface IRecordProcessor. And KCL will call this class and process records from kinesis. But when I tried to use dependency injection, I found it was not succeeded.
Here's the snippet for RecordProcessor:
#Component
public class RecordProcessor implements IRecordProcessor {
#Autowired
private SingleRecordProcessor singleRecordProcessor;
#Override
public void initialize(String shardId) {
...
}
#Override
public void processRecords(List<Record> records, IRecordProcessorCheckpointer checkpointer) {
...
}
}
I use Class SingleRecordProcessor to process single each record from kinesis. And this is my SingleRecordProcessor class snippet:
#Component
public class SingleRecordProcessor {
private Parser parser;
private Map<String, Table> tables;
public SingleRecordProcessor() {
}
#Autowired
private void setParser(Parser parser) {
this.parser = parser;
}
#Autowired
private void setTables(Map<String, Table> tables) {
this.tables = tables;
}
public void process(String record) {
...
}
}
I want to let spring framework automatically inject the SingleRecordProcessor instance into the class and use it. But I found that the field singleRecordProcessor is null.
Any idea why the dependency injection is failed? Or is it impossible to inject dependencies into a class which is called by other framework (in this case it's KCL)? Any suggestions will be appreciated! Really need some help please!!
[UPDATE]:
Sorry for not expressing the error clearly. The error was NullPointerException. I tried to inject singleRecordProcessor and call method process() on it. I think the injection was not successful so the instance singleRecordProcessor is null and there comes the NullPointerException.
More information is as follows:
I have a major class called Application
#SpringBootApplication
public class Application{
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new ApplicationPidFileWriter("./app.pid"));
ConfigurableApplicationContext ctx = application.run(args);
}
}
And I have the MainProcessor class which will call KCL.
#Service
public final class MainProcessor {
#EventListener(ApplicationReadyEvent.class)
public static void startConsumer() throws Exception {
init();
IRecordProcessorFactory recordProcessorFactory = new RecordProcessorFactory();
Worker worker = new Worker(recordProcessorFactory, kinesisClientLibConfiguration);
...
worker.run(); // this line will call KCL library and eventually call ProcessorRecord class.
}
}
[UPDATE2]
RecordProcessorFactory only has one method like this
#Component
public class RecordProcessorFactory implements IRecordProcessorFactory {
#Autowired
RecordProcessor recordProcessor;
#Override
public IRecordProcessor createProcessor() {
return recordProcessor;
}
}
It creates a new RecordProcessor instance for KCL to use it.
You should autowire an instance of this into your MainProcessor:
#Component
public class RecordProcessorFactory {
#Lookup IRecordProcessor createProcessor() { return null; }
}
Spring will instantiate a RecordProcessorFactory for you, and replace the implementation of createProcessor() in it with one that will return a new IRecordProcessor each time it's called. Both the factory and the processors will be Spring beans - which is what you want.

Spring injected beans null in nested class

I have a class with 2 static nested classes that do the same operation on 2 different generic types.
I exposed the 2 classes as beans and added #Autowired for the constructors as I usually do.
Here is the basic setup
abstract class <T> Parent implements MyInterface<T> {
private final Service service;
Parent(Service service){ this.service = service; }
#Override public final void doInterfaceThing(T thing){
T correctedT = map(thing);
service.doTheThing(correctedT);
}
protected abstract T map(T t);
#Service
public static class ImplA extends Parent<A> {
#Autowired ImplA (Service service){ super(service); }
A map(A a){ //map a }
}
#Service
public static class ImplB extends Parent<B> {
#Autowired ImplB (Service service){ super(service); }
B map(B b){ //map b }
}
}
And in another class I have
#Service
public class Doer {
private final List<MyInterface<A>> aImpls;
#Autowired public Doer(List<MyInterface<A>> aImpls){ this.aImpls = aImpls; }
public void doImportantThingWithA(A a){
aImpls.get(0).doInterfaceThing(a);
}
}
When I run the app, everything appears to be injected correctly and when I put a breakpoint in the ImplA and ImplB constructors, I have a not-null value for "service". I also have an ImplA bean in the aImpls list in Doer.
When I call doImportantThingWithA(a) however, "service" is null inside ImplA and I obviously die.
I'm not sure how this is possible because:
I see a nonnull value in my constructors for service which is a final field.
If spring is injecting ImplA and ImplB into another class, it should already have either injected a Service into ImplA or ImplB, or thrown an exception on bean initialization. I have nothing set to lazily load and all bean dependencies are required.
The reason for the nested classes is because the only thing that changes between the 2 implementations is the map() function. Trying to avoid extra classes for 1 line of varying code.
More info:
When I add a breakpoint in Parent.doInterfaceThing(), if I add a watch on "service" I get null as the value. If I add a getService() method, and then call getService() instead of referring directly to this.service, I get the correct bean for service. I don't know the implications of this but something seems weird with the proxying.
It looks like what is causing the issue is Parent.doInterfaceThing();
If I remove final from the method signature, "service" field is correctly populated and the code works as expected.
I don't understand at all why changing a method signature affects the injected value of final fields in my class... but it works now.
What I meant with my "use mappers" comment was something like this:
class MyInterfaceImpl implements MyInterface {
#Autowired
private final Service service;
#Override public final <T> void doInterfaceThing(T thing, UnaryOperator<T> mapper){
T correctedT = mapper.apply(thing);
service.doTheThing(correctedT);
}
// new interface to allow autowiring despite type erasure
public interface MapperA extends UnaryOperator<A> {
public A map(A toMap);
default A apply(A a){ map(a); }
}
#Component
static class AMapper implements MapperA {
public A map(A a) { // ... }
}
public interface MapperB extends UnaryOperator<B> {
public B map(B toMap);
default B apply(B b){ map(b); }
}
#Component
static class BMapper implements MapperB {
public B map(B a) { // ... }
}
}
This does have a few more lines than the original, but not much; however, you do have a better Separation of Concern. I do wonder how autowiring works in your code with the generics, it does look as if that might cause problems.
Your client would look like this:
#Service
public class Doer {
private final List<MapperA> aMappers;
private final MyInterface myInterface;
#Autowired public Doer(MyInterface if, List<MapperA> mappers){
this.myInterface = if;
this.aImpls = mappers; }
public void doImportantThingWithA(A a){
aMappers.stream().map(m -> m.map(a)).forEach(myInterface::doInterfaceThing);
}
}

asEagerSingleton with factory

I'm very new to Guice, but I have a singleton that I believe would normally be created thusly:
#Provides
#Singleton
private SomeClass getSomeClass()
{
return someClassFactory(configuration);
}
However, I want this to be eagerly initialized. When I remove the #Singleton annotation and try to bind(SomeClass.class).asEagerSingleton() I get errors:
1) No implementation for SomeClass was bound.
2) A binding to SomeClass was already configured
How can I provide an Eagerly initialized singleton that is constructed with parameters or a factory?
The #Provides annotation is a separate way to configure a binding for SomeClass; it's conflicting with the bind(SomeClass.class).asEagerSingleton() binding.
To fix it, you'll need to write an explicit provider class and bind it using toProvider:
class MyModule extends AbstractModule {
private static class MyProvider implements Provider<SomeClass> {
private final OtherStuff otherStuff;
#Inject
MyProvider(OtherStuff otherStuff) {
// Inject constructor params if your #Provides method took arguments
this.otherStuff = otherStuff;
}
public SomeClass get() {
return new SomeClass(otherStuff);
}
}
protected void configure() {
bind(SomeClass.class).toProvider(MyProvider.class).asEagerSingleton();
}
}

One dependency in multiple services classes with Dagger 2

I want to inject a custom class as an dependency in different service classes, but I don't get it work. It always ends with a NPE. Here is my example (simple Java SE) ...
My Main class to get everything running
public class Main {
public static void main(String[] args) throws IOException, TimeoutException {
MyApplication MyApp = new MyApplication();
MyApp.execute();
}
}
MyApplication class
public class MyApplication {
private MyApplicationComponent appComponent;
#Inject FooService fooService;
#Inject BarService barService;
#Inject BazService bazService;
public MyApplication() {
component = DaggerMyApplicationComponent.builder().build();
component.inject(this);
}
public void execute() {
fooService.doStuff();
barService.doStuff();
// this will happen in the FooService construct, see below
// bazService.doStuff();
}
}
Component and Module classes as defined in Dagger, without using it the #Inject constructor way
#Singleton
#Component(modules = {MyApplicationModule.class})
public interface MyApplicationComponent {
void inject(MyApplication application);
}
#Module
public class MyApplicationModule {
#Singleton
#Provides
FooService provideFooService() {
return new FooService();
}
#Singleton
#Provides
BarService provideBarService() {
return new BarService();
}
#Provides
BazService provideBazService() {
return new BarService();
}
}
Using the MyApplicationModule and MyApplicationComponent to provide needed dependencies works within the Main.class. I also want to use the BazService within the FooService class. Therefore I use the #Inject way to define it as a dependency with FooService.class.
Using #Inject of BazService within the FooService.class
public class FooService {
#Inject BazService bazService;
public FooService(){}
public doStuff(){
bazService.doStuff();
}
}
Running the Main.class always ends within a NPE, due to undefined bazService in the FooSerivce class. I don't think, that I missed to add an annotation anywhere. I think Dagger will not work this way ... any ideas?
FooService expects bazService to be injected though field injection but you are calling bazService before this happens. If you want to call bazService.doStuff() in FooService's constructor you'll have to use constructor injection.

Categories