Why this constructor argument is not working - java

I created a new class with below piece of logic.
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
import com.google.protobuf.ByteString;
import java.util.List;
import java.util.logging.Logger;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.threeten.bp.Duration;
#Component
#RefreshScope
public class PrimeChannel {
private final EnhancedBigtableStubSettings enhancedBigtableStubSettings;
private final List<String> tableIds;
public PrimeChannel(EnhancedBigtableStubSettings enhancedBigtableStubSettings, List<String> tableIds) {
this.enhancedBigtableStubSettings = enhancedBigtableStubSettings;
this.tableIds = tableIds;
}
}
While running i am getting below error
Parameter 0 of constructor in myPackage.PrimeChannel required a bean of type 'com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings' that could not be found.
Action:
Consider defining a bean of type 'com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings' in your configuration.
I am passing EnhancedBigtableStubSettings object as first parameter then why its not considering.
if i try with 0 argument constructor by initializing EnhancedBigtableStubSettings as null will throws null pointer exception in later stages.
How can deal with this?
Can anyone help on this?

At first, you must create a bean of EnhancedBigtableStubSettings class. You can define it in applicationContext.xml or #Configuration class, then annotate the constructor with #Autowired.
<bean name="beanName" class="foo.EnhancedBigtableStubSettings"/>
#Bean(name = "beanName")
public EnhancedBigtableStubSettings getEnhancedBigtableStubSettings() {
//return object somehow
return new EnhancedBigtableStubSettings();
}

Related

Implement Interface with custom method and JpaRepository

so I'm working on an API Rest, registration for students, using Domain Driven Design. So my problem is: I'm trying to add a custom method with the JpaRepository. My Project hierarchy is:
com.wizardry.witchcraft.domain.model.StudentModel;
com.wizardry.witchcraft.infraestructure.repository.CustomRepositoryImpl;
com.wizardry.witchcraft.domain.repository.IStudentRepository;
com.wizardry.witchcraft.domain.repository.ICustomRepository;
com.wizardry.witchcraft.api.controller.TesteController2;
com.wizardry.witchcraft.api.controller.StudentController;
So first I've created the method Implementation
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import com.wizardry.witchcraft.domain.model.StudentModel;
import com.wizardry.witchcraft.domain.repository.ICustomRepository;
#Repository
public class CustomRepositoryImpl implements ICustomRepository {
#PersistenceContext
private EntityManager manager;
#Override
public List<StudentModel> findCustom (String name){
//METHOD
}
}
And the Interface:
import com.wizardry.witchcraft.domain.model.StudentModel;
public interface ICustomRepository {
List<StudentModel> findCustom(String name);
}
And to test it out I created a new Controller to don't mess with my working one, TesteController2, and it worked fine. So my next step was extended the ICustomRepository in the IStudentRepository, made the changes in TesteController2 and then Spring won't find my findCustom method anymore, It tries to create the method as a JPA keyword and return and error. This is my repository interface:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.wizardry.witchcraft.domain.model.StudentModel;
#Repository
public interface IStudentRepository extends ICustomRepository, JpaRepository<StudentModel, Long> {
List<StudentModel> queryByName(String name, #Param ("id") Long school);
List<StudentModel> queryFirstByNameContaining(String name);
List<StudentModel> queryTop2ByNameContaining(String name);
int countByWizardingSchoolModelId(Long school);
}
And the TesteController2:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.wizardry.witchcraft.domain.model.StudentModel;
import com.wizardry.witchcraft.domain.repository.IStudentRepository;
#RestController
#RequestMapping(value = "/test")
public class TesteController2 {
#Autowired
private IStudentRepository iStudentRepository;
#ResponseStatus(HttpStatus.ACCEPTED)
#GetMapping
public List<StudentModel> findCustom2(String name) {
return iStudentRepository.findCustom(name);
}
}
PS: I have a Service Layer com.wizardry.witchcraft.domain.service.RegisterStudentService however
the method in question does not go through it(yet!) because I'm testing, I tried to pass by the service and see what happen but give the same ERROR.
*
ERROR: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentController': Unsatisfied dependency expressed through field 'registerStudentService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'registerStudentService': Unsatisfied dependency expressed through field 'iStudentRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'IStudentRepository' defined in com.wizardry.witchcraft.domain.repository.IStudentRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.wizardry.witchcraft.domain.repository.ICustomRepository.findCustom(java.lang.String)! No property findCustom found for type StudentModel!
*
Thanks in Advance! I'm really lost here.
Just rename your class CustomRepositoryImpl to IStudentRepositoryImpl and it should work.
#Repository
public class IStudentRepositoryImpl implements ICustomRepository {
#PersistenceContext
private EntityManager manager;
#Override
public List<StudentModel> findCustom (String name){
//METHOD
}
}
Below is the documentation from Spring
Configuration If you use namespace configuration, the repository
infrastructure tries to autodetect custom implementations by scanning
for classes below the package we found a repository in. These classes
need to follow the naming convention of appending the namespace
element's attribute repository-impl-postfix to the found repository
interface name. This postfix defaults to Impl.
https://docs.spring.io/spring-data/data-commons/docs/current-SNAPSHOT/reference/html/#repositories.custom-implementations

No bean named '' is defined [duplicate]

This question already has an answer here:
Is it possible to set a bean name using annotations in Spring Framework?
(1 answer)
Closed 4 years ago.
I am testing out simple AOP use case in Spring but am getting the below error,
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'bean1' is defined
Below are my source files,
DemoConfig.java
package com.luv2code.aopdemo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.luv2code.aopdemo.aspect.MyDemoLoggingAspect;
import com.luv2code.aopdemo.dao.AccountDAO;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("com.luv2code.aopdemo")
public class DemoConfig {
#Bean
#Qualifier("bean1")
public AccountDAO accDao() {
return new AccountDAO();
}
#Bean
#Qualifier("bean2")
public MyDemoLoggingAspect myAscpect() {
return new MyDemoLoggingAspect();
}
}
MyDemoLoggingAspect.java
package com.luv2code.aopdemo.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class MyDemoLoggingAspect {
// this is where we add all of our related advices for logging
// let's start with an #Before advice
#Before("execution(** com.luv2code.aopdemo.dao.AccountDAO.addAccount(..))")
public void beforeAddAccountAdvice() {
System.out.println("\n=====>>> Executing #Before advice on addAccount()");
}
}
MainDemoApp.java
package com.luv2code.aopdemo;
import com.luv2code.aopdemo.dao.AccountDAO;
public class MainDemoApp {
public static void main(String[] args) {
// read spring config java class
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
// get the bean from spring container
AccountDAO theAccountDAO = context.getBean("bean1", AccountDAO.class);
// call the business method
theAccountDAO.addAccount();
// do it again!
System.out.println("\nlet's call it again!\n");
// call the business method again
theAccountDAO.addAccount();
// close the context
context.close();
}
}
I have given my bean ID "bean1", even after that Spring is not able to find my bean in the context. Why am I getting this error and how to resolve this?
The #Qualifier tag is used with the #Autowired annotation.
What you need is
#Bean(name="bean1")
public AccountDAO accDao() {
return new AccountDAO();
}

Why is #PostConstruct recognised in my case?

Could you tell me why does a method annotated with #PostContruct runs in my case? As far as I know, a method with #PostContruct is processed by Bean Post Processors. If you want to activate the default CommonAnnotationBeanPostProcessor you need to add <context:annotation-config/> in the XML configuration but I want to use only annotation config. In my case, #ComponentScan in configuration is pointed to the service. It means that only classes from this package candidates to be instantiated.
Configuration class:
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "service")
public class AppConfig {
}
Simple class:
package service;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component
public class Simple {
#PostConstruct
private void sout(){
System.out.println("SOUT");
}
}
And the launcher:
import config.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import service.Simple;
public class Launcher {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
Simple simple = ctx.getBean("simple", Simple.class);
}
}
The output of the app is "SOUT". Could you explain be who invokes the #PostContruct method and how?
AnnotationConfigApplicationContext is an alternative to XML based configurations. When you use it to create objects, it first creates the object and the #Autowired properties, and then calls the #PostConstruct method. It is a handy alternative to writing a setup() or init() method which you would have to call yourself.

No qualifying bean of type is defined when running a main method

I've seen a lot of questions about this error before, but no resolution that works for me.
I'm new to Spring, but trying to use the Spring Data for Neo4J library for a project. I decided to start with a quick spike to make sure I know how everything is working, and so I set up a simple App class with a main method like so:
package org.example.neo4jSpike;
import org.example.neo4jSpike.domain.Actor;
import org.example.neo4jSpike.repositories.ActorRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
/**
* Hello world!
*
*/
#Component
public class App
{
#Autowired
private ActorRepository actors;
#SuppressWarnings("resource")
public static void main( String[] args )
{
ApplicationContext context = new AnnotationConfigApplicationContext(SpikeConfiguration.class);
App a = context.getBean(App.class);
a.init();
}
private void init(){
Actor michaelDouglas = actors.save(new Actor("Michael Douglas"));
System.out.println( "Hello World!" );
System.out.println(michaelDouglas.getId());
System.out.println("Total people: " + actors.count());
}
}
I have the configuration class setup as well:
package org.example.neo4jSpike;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableNeo4jRepositories(basePackages = "org.example.neo4jSpike.repositories")
#EnableTransactionManagement
public class SpikeConfiguration extends Neo4jConfiguration{
#Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory("org.example.neo4jSpike.domain");
}
// needed for session in view in web-applications
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}
I'll add the code for my repositories and domain classes if needed, but they're all set up in a similar manner, and are all pretty simple.
When I try and run the main, however, I get
No qualifying bean of type [org.example.neo4jSpike.App] is defined
I don't see how it's not defined, it's right there, defined as an #Component. What am I misunderstanding?
Doesn't matter if you put the #Component annotation if Spring is not scanning your class package. You can add a #ComponentScan annotation in you configuration class and configure it to scan the package where your App class is located. Alternatively you can remove the #Component annotation and declare a Bean of type App in the configuration class.
Hope this can help.

Autowiring for #Service field failed

I keep looking at my codes all day along, I can't find the cause. The repository (#Repository) is working just fine, it's the #Service field that I keep failing get it autowired, I keep struggling since everything looks fine
The dispatched servlet:
<mvc:annotation-driven />
<context:component-scan base-package="com" />
com.repository
Repo.java
package com.repository;
import com.domain.Student;
import java.util.List;
public interface Repo { public List<Student> getAllSiswa(); }
RepoImplement.java
import com.domain.Student;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
#Repository
public class RepoImplement implements Repo {
List<Student> ls = new ArrayList<>();
public RepoImplement(){
Student s1 = new Student();
s1.setNama("paul");
Student s2 = new Student();
s2.setNama("robert");
ls.add(s1);
ls.add(s2);
}
#Override
public List<Student> getAllSiswa() {
return this.ls;
}
}
package com.service;
Serve.java
import com.domain.Student;
import java.util.List;
public interface Serve {
void changeName(String namaBaru);
public List<Student> newList();
}
I'm suspecting there's something wrong over here
ServeImplement.java
import com.domain.Student;
import com.repository.Repo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ServeImplement implements Serve {
#Autowired
public Repo repo;
List<Student> s = repo.getAllSiswa(); // THIS IS SUSPECTING ME.
#Override
public void changeName(String namaBaru) {
s.get(0).setNama(namaBaru); // get first Student, then update its name.
}
#Override
public List<Student> newList() {
return this.s;
}
}
controller2.java (it's the mapping request for serving student)
package com.controlller;
import com.domain.Student;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.service.Serve;
#Controller
public class controller2 {
#Autowired
public Serve serv;
#RequestMapping("/changename")
public ModelAndView sdaf() {
serv.changeName("New name");
List<Student> list = serv.newList();
return new ModelAndView("page2", "out", list);
}
}
The error:
Error creating bean with name 'controller2': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: public com.service.Serve
com.controlller.controller2.serv; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'serveImplement' defined in file
[C:\Users\hans\Documents\NetBeansProjects\WebApplication2\build\web\WEB-INF\classes\com\service\ServeImplement.class]:
Instantiation of bean failed; nested exception is
org.springframework.beans.BeanInstantiationException: Could not
instantiate bean class [com.service.ServeImplement]: Constructor threw
exception; nested exception is java.lang.NullPointerException
You need to understand how autowiring, or in fact Java in general, works.
Spring must create an instance of your ServImpl class, and populate the field repo with the repository bean. It does that using reflection, but what it does is basically equivalent to the following code:
ServImpl s = new ServImpl();
s.repo = theRepoBean;
So, you see that s.repo becomes non-null after the constructor has been executed. And, while executing the constructor, the following line of code is executed:
List<Student> s = repo.getAllSiswa();
At that moment, repo hasn't been initialized yet. So it's null. So you get a NullPointerException.
Use constructor injection instead of field injection, or use a #PostConstruct annotated method.
And please, make your fields private instead of public.
That said, the goal of a repository is normally to get data from a database. And the students can be modified,deleted or created in the database. So initializing a field of your service and returning always the same list defeats the whole point of having a repo. You should call repo.getAllSiswa() from newList(), every time it's called, to get the latest, up-to-date, list of students.
Because Autowired on field happens right after construction, you need to change your code in order to get it to work.
This should works:
#Service
public class ServeImplement implements Serve {
public Repo repo;
List<Student> s;
#Autowired
public ServeImplement(Repo repo) {
this.repo = repo;
s = repo.getAllSiswa();
}
#Override
public void changeName(String namaBaru) {
s.get(0).setNama(namaBaru); // get first Student, then update its name.
}
#Override
public List<Student> newList() {
return this.s;
}
}
Moreover, using Autorwired annotation on constructor allow you to mark your field as final if the instance shouldn't have to change.

Categories

Resources