How to make Depedency Inject in a not "RequestMapping" method - java

Can i make my repository be accessed in a class who isn't a RestController or something like that ?
I have an WatchService who listen a folder, to reads the files and after persist to a database. My watchservice works just like reading files, but I want persist using my JPARepository to persists, can i do that?
Springboot Application v2.1.6.RELEASE
#Repository
public interface MyRepository extends JpaRepository<MyClass, Long> { }
public class MyWatchService implements Runnable{
#Autowired
private MyRepository myRepository;
// SOME CODES COMES HERE
#Override
public void run() {
// SOME CODES COMES HERE
myRepository.save(MyClass); // In this point give a nullPointerException
}
}
I get that Exception:
java.lang.NullPointerException
at com.WatchService.run(WatchService.java:515)
at java.base/java.lang.Thread.run(Thread.java:835)

You get the NullPointerException because the dependency did not get injected. You used the annotation correctly, but the dependencies do not get injected, by some magic.
In order for this to work (i.e. for the beans to get injected), you need to let the DI- or IoC Container instantiate the bean for your (in JEE this would be CDI, in Spring it is the Spring IoC Container). This can be done by injection (d'uh! Injection-inception) or programmatically.
A Spring-centric solution is explored in this question.

Related

How can I do CRUD operations through CrudRepository in Spring?

I'm working with PostgresSQL and I have the following interface:
#Repository
public interface ExampleRepository extends CrudRepository<ExampleEntity, Long> { }
Then I try to get the bean:
ExampleRepository repository = ctx.getBean(ExampleRepository.class);
Of course, I can't do that, because there's no implementation and eventually I get
NoSuchBeanDefinitionException: No qualifying bean of type 'ExampleRepository'
I know this is a wrong approach, but since I'm not enough experienced, I've got no idea how I can communicate with my database. Any example I searched only explained how to implement services & controllers in order to interact with db through Browser. But I want to do CRUD operation inside the java code.
Could anyone explain it to me? Any related sources would also be fine.
I am not sure how you are getting context (ctx) here.
But the common approach is #Repository is not needed instead, #EnableJPARepositories should be used in the #Configuration file. Then use #Autowired to inject the repository into your service class (where you want to execute operation from your repository bean)
You can refer below link for more details
https://mkyong.com/spring-boot/spring-boot-spring-data-jpa/
You don't need to create bean. It will created by the spring framework because you annotated your interface as #Repository .You need only #Autowired in your service class or where do you want to use this reference.
#Autowired
private ExampleRepository exampleRepository;

Autowire all components in a package without implementing an interface

I got a project with tons of services and repositories. Currently each repository is autowired to a service using annotations.
#Service
public class Service1 {
#Autowired
private Repository1 repository1;
#Autowired
private Repository2 repository2;
...100+ more
}
All of these repository are under the same package. Is it possible to skip declaration for each repository?
A simple solution I found would be to implement an interface like this:
#Autowired
private Map<String,RepositoryInterface> repositoryInterface
public void method1(){
repositoryInterface.get("repository1").doMethod();
}
It should have been a good solution but problem is I don't have access to all the source codes. I have tons of repository classes that I am not allowed to change to add an interface class.
So is there another way to solve this? Like just scan the whole package and just use bean name to access the repositories?
Beans are retrievable from their class or their name (and both).
In your case, you could rely directly on their class to retrieve them from the context.
Inject an ApplicationContext (or constructor way) :
#Autowired
private ApplicationContext applicationContext;
And use it :
applicationContext.getBean(RepositoryOne.class).doMethod1();
Ideally it should be extracted into a method :
public <T> T getRepository(Class<T> clazz){
return applicationContext.getBean(clazz);
}
to be used more simply :
getRepository(RepositoryOne.class).doMethod(1);
But I would warn about needing so many field dependencies in a class.
This makes it very hard to maintain/to test and also very error prone to use.
The best thing to do is rethink your design to avoid such complex/bloat class.
Besides using structure like private Map<String,RepositoryInterface> repositoryInterface or ApplicationContext will make you lose the benefit from dependency checks performed by the Spring container at startup that prevents NullPointerException and errors related to inconsistency (dependency missing) during the application working.

How to set the attributes to a generic #Service class in Spring Boot?

I'm new to Spring Boot, so bare me with my basic question here.
I want to build a generic #Service class that has well defined methods that don't even need to be overwritten.
The only thing this class needs is to adjust its attributes based on which Controller method was called. Basically, this class works as a Job handler that needs to adjust some parameters so its methods can perform what they're supposed to compute. The job will always have the same workflow, calling the methods in the same order, but it will obtain different results depending on the parameters/attributes it receives, which, as I said before, are defined by the controller methods.
The only attribute it has beside the ones that adjust the job's workflow is an autowired #Repository object that will save the results of the job in a database.
Maybe I could simply instantiate an Job Handler object and call a constructor with the paramaters I need for the job, but I don't know what is the "Spring way" of doing this, considering how Spring works with dependency injection and I need a #Repository object embbeded into the Job Handler service.
I would really appreciate if anyone could write a sample code/example so I could understand how this can be done with Spring Boot so I don't have to duplicate code or Service Classes.
The Spring way for this case would be to create a Bean of your JobHandler, where you inject the necessary dependencies, like your Repository:
#Configuration
class MyConfiguration {
#Bean
MyJobHandler myJobHandler(MyRepository myRepository) {
return new MyJobHandler (myrepository);
}
}
Alternatively, if you do not want a configuration class, you could declare your JobHandler as a Component and inject the repository in the constructor:
#Component
class MyJobHandler {
private MyRepository myRepository;
public MyJobHandler myJobHandler(MyRepository myRepository) {
this.myRepository = myRepository;
}
}

Autowired failing to load service into class

I'm receiving a null pointer exception when operating on my service because my service is not being Autowired into the class. I've implemented this class's repository and service exactly the same as others in this application and I haven't had this problem before. The class does in fact warn about issues with the Autowire but I'm not sure how to fix them:
Autowired members must be defined in valid spring bean
Again, this is set up the same as other classes and I do not have this issue. Within the service class, it complains that the repository cannot be autowired into the constructor because there are multiple beans of the same type. My other service class shows this warning as well but does not have problems being Autowired into classes and operated upon. Definitions below, please ask for any other context that would be helpful.
//TransactionCategoryRepository.java
#Repository("transactionCategoryRepository")
public interface TransactionCategoryRepository extends
CrudRepository<TransactionCategory, Integer> {
}
--
//TransactionCategoryService.java
#Service("transactionCategoryService")
public class TransactionCategoryService {
private TransactionCategoryRepository transactionCategoryRepository;
#Autowired
public TransactionCategoryService(TransactionCategoryRepository repository) {
this.transactionCategoryRepository = repository;
}
public void saveTransactionCategory(TransactionCategory transactionCategory) {
transactionCategoryRepository.save(transactionCategory);
}
}
--
//Utilities.java
public class PlaidUtilities {
private Logger logger =
LoggerFactory.getLogger(PlaidUtilities.class.getSimpleName());
private PlaidClient mPlaidClient;
#Autowired
TransactionCategoryService mTransactionCategoryService;
...
The multiple bean warning is thrown on respository in TransactionCategoryService.java and the Autowired definition warning is thrown in Utilities.java. The breaking null pointer exception error occurs later in Utilities.java when operating on mTransactionCategoryService.
Unless you need them, take the names out of the #Service and #Repository annotations. I've found it just makes things awkward.
The other thing that might be wrong is that you're not scanning those packages. You can change that in your main class by altering the boot application attribute to #SpringBootApplication(scanBasePackages={"your.package.here"})
Have a look here at this question where they detail it

#Inject annotation not working

I'm trying to use CDI for the first time. While I have successfully injected one EJB inside another using #EJB, I can't get the #Inject annotation to work.
#Stateless
public class AccountDaoImpl implements AccountDAO {
#Inject
private MultiTenantEntityManagerImpl mtem; //always null
}
And the multi-tenancy entity manager looks like this:
#Default
public class MultiTenantEntityManagerImpl {
.....
}
I've created a beans.xml file (empty) but and shoehorned it into the META-INF folder in the built jar file. Still no joy.
I'm sure it's something simple. I'm running in jboss 5.0.1.GA.
Update
So it looks like the #Inject annotation is not supported in jboss 5.
An alternative is to use the #EJB annotation, but this isn't working either:
#Stateless
public class AccountDaoImpl implements AccountDAO {
#EJB
private MultiTenantEntityManager mtem; //still null!
}
Weirdly, in another EJB, this exact declaration of the entity manager is working fine.
in my case i was missing subsystem in the standalone
It looks like, in jboss 5 at least, an #EJB annotation will only be respected if both the following conditions hold:
The class in which you're using it is an EJB
The class is retrieved from the container somehow (eg JNDI), rather than being simply instantiated via a constructor.

Categories