I have following repository which extends jpa repositroy and also have an implementation class where i have autowired this.
#Repository
public interface ProjectDAO extends CrudRepository<Project, Integer> {}
#Service
public class ProjectServiceImpl {
#Autowired private ProjectDAO pDAO;
public void save(Project p) { pDAO.save(p); } }
Now i have one Application.java class
Class Application{
public static void main(String..s){
// I need a way to call a method of repository
}
}
configuration file
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories
#PropertySource("file:/Users/abc/Documents/application.properties")
public class PersistenceContext {
#Autowired
Environment environment;
So how do we call this from main in case i dont to use any web based controller?
This is a way:
class Application {
public static void main(String[] s){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
ProjectDAO dao = applicationContext.getBean(ProjectDAO.class);
}
}
Edit:
class Application {
public static void main(String[] s){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
ProjectServiceImpl service = applicationContext.getBean(ProjectServiceImpl.class);
}
}
Related
Hi I am trying to use Strategy Design pattern. I am getting ReEncryptionOperation bean as null in my TestServiceImpl class.
this is my interface
public interface ReEncryptionOperation {
void performOperation (String name);
}
These are my implementation classes
public class Test1 implements ReEncryptionOperation {
#Override
public void performOperation(String name){
return ....;
}
}
public class Test2 implements ReEncryptionOperation {
#Override
public void performOperation(String name) {
return ....;
}
}
This is my configuration class where I am defining as a bean
#Configuration
#Slf4j
public class TestConfiguration
{
#Bean("reEncryptionOperation")
public ReEncryptionOperation getReEncryptionOperation () throws ReEncryptionException {
if (annotationSupport) {
return new Test1();
}
return new Test2();
}
}
this is my service class where i am trying to use ReEncryptionOperation using #Autowired. But I am getting null.
#Component
#Slf4j
public class TestServiceImpl
{
#Autowired
private ReEncryptionOperation reEncryptionOperation;
public ReEncryptionResponse submitJob (
final ReEncryptionRequest reEncryptionRequest) throws ReEncryptionException
{
reEncryptionOperation.performOperation(test);
}
}
Your configuration seems ok.
Check that TestConfiguration is located in a package scanned by spring.
To be sure your bean is created on runtime, place a breakpoint in the method getReEncryptionOperation
This question already has answers here:
Injecting beans into a class outside the Spring managed context
(8 answers)
Closed 3 years ago.
Suppose I have
#Service
public class myService () {
public void sayHello() {
System.out.println("Hello");
}
}
public class myTestClass() {
#Autowired
private myService thisService;
public void transferHello() {
thisService.sayHello();
}
}
public class Application() {
public static void main(String[] args) {
SpringApplication.run(PilContainerApplication.class, args);
myTestClass thisTest = new myTestClass();
thisTest.transferHello();
}
}
Since myTestClass() is not a bean like service/controller, thisService would have a null reference when I use myTestClass thisTest = new myTestClass();.
I was wondering how to overcome this.. I tried using public static myService thisService and it said cannot use #Autowired on static fields.
Thank you
When a class cannot be changed to be annotated with a Spring stereotype, #Bean is a very good alternative :
#Configuration
public class MyBeansConfiguration {
#Bean
public MyTestClass getMyTestClass(MyService myService) {
return new MyTestClass(myService);
}
}
You can inject it now in your Application class :
public class PilContainerApplication {
#Autowired
MyTestClass myTestClass;
#PostConstruct
public void init(){
myTestClass.transferHello();
}
public static void main(String[] args) {
SpringApplication.run(PilContainerApplication.class, args);
}
}
Note that beans are instances of class and are injected in other instances of class that depend on them. So you don't have access to the injected beans in the static main() method. But you have access to it in an instance method annotated with #PostConstruct that will be executed when the dependencies were injected in the current bean.
Side note : classes have to start with an uppercase. I did it in the provided code.
if you want inject bean B without marking bean A via some annotation, or xml definition, you can use SpringBeanAutowiringSupport
public class A {
#Autowired
private class B b;
public A{
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
}
I have below project structure
My code files are as belows
DemoApplication.java
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
CarListGrabber grabber = new CarListGrabber();
grabber.grabCarsWithName("Test");
}
}
NewCarRepository.java
#Repository
public interface NewCarRepository extends CrudRepository<NewCar, Long> {
}
NewCar.java
#Entity
#Table(name = "new_car_details")
public class NewCar {
// member variables with default constructor
}
CarListGrabber.java
#Service
public class CarListGrabber {
#Autowired
private NewCarRepository newCarRepository;
// someOtherStuff
}
Even though I have used annotations #Repository, #Service I am getting null repository object in service.
You are instantiating a new CarListGrabber with:
CarListGrabber grabber = new CarListGrabber();
it will not make injections you need to inject also your grabber, like:
#Autowired
CarListGrabber grabber;
I have a simple Spring Boot web project, right from a template:
#SpringBootApplication
#RestController
public class HelloWorldRestApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = new Performer();
p.perform();
}
}
I have a test to ensure autowiring works, and in fact it does in this test class (examples come from Spring in Action, 4th):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
#Autowired
private CDPlayer cdp;
#Test
public void cdShouldNotBeNull(){
assertNotNull(cdp);
}
}
and:
public class Performer {
#Autowired
private CDPlayer cdp;
public void perform(){
System.out.println(cdp);
cdp.play();
}
public CDPlayer getCdp() {
return cdp;
}
public void setCdp(CDPlayer cdp) {
this.cdp = cdp;
}
}
and:
#Component
public class CDPlayer{
public void play(){
System.out.println("play");
}
}
config:
#Configuration
#ComponentScan
public class CDPlayerConfig {
}
However, it doesnt work in HelloWorldRestApplication, I get null.
Adding #ContextConfiguration(classes=CDPlayerConfig.class) doesn't help.
What do I miss?
Try enabling #ComponentScan your packages in your main class and get Performer class instance from ApplicationContext as below:
#SpringBootApplication
#RestController
#ComponentScan({“package.name.1”,”package.name.2”})
public class HelloWorldRestApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(HelloWorldRestApplication.class, args);
Performer p = ctx.getBean(Performer.class);//get the bean by type
p.perform();
}
}
I'm a newbie to Spring. I'm facing a problem with Spring-Boot. I'm trying to autowire a field from an external config file into an autowired bean. I have the following classes
App.java
public class App {
#Autowired
private Service service;
public static void main(String[] args) {
final SpringApplication app = new SpringApplication(App.class);
//app.setShowBanner(false);
app.run();
}
#PostConstruct
public void foo() {
System.out.println("Instantiated service name = " + service.serviceName);
}
}
AppConfig.java
#Configuration
#ConfigurationProperties
public class AppConfig {
#Bean
public Service service() {
return new Service1();
}
}
Service Interface
public interface Service {
public String serviceName ="";
public void getHistory(int days , Location location );
public void getForecast(int days , Location location );
}
Service1
#Configurable
#ConfigurationProperties
public class Service1 implements Service {
#Autowired
#Value("${serviceName}")
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.
public void getHistory(int days , Location location)
{
//history code
}
public void getForecast(int days , Location location )
{
//forecast code
}
}
I'm unable to display the service name variable in the postconstruct method of the App class. Am I doing this right?
You can load properties in different ways:
Imagine the following application.properties which is automatically loaded by spring-boot.
spring.app.serviceName=Boot demo
spring.app.version=1.0.0
Inject values using #Value
#Service
public class ServiceImpl implements Service {
#Value("${spring.app.serviceName}")
public String serviceName;
}
Inject values using #ConfigurationProperties
#ConfigurationProperties(prefix="spring.app")
public class ApplicationProperties {
private String serviceName;
private String version;
//setters and getters
}
You can access to this properties from another class using #Autowired
#Service
public class ServiceImpl implements Service {
#Autowired
public ApplicationProperties applicationProperties;
}
As you can notice the prefix will be spring.app then spring-boot will match the properties prefix with that and look for serviceName and version and values will be injected.
Considering you have you class App annotated with #SpringBootApplication and App class in the top package You can put your serviceName inside application.properties and inject it using #Value("${serviceName}"). Do not use #Component on a class if you are already using #Bean on configuration it will clash, and so #Autowired with #Value
See docs for more info
You will end with something like
#Service // #Component specialization
public class Service1 implements Service {
#Value("${serviceName}")
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.
public void getHistory(int days , Location location)
{
//history code
}
public void getForecast(int days , Location location )
{
//forecast code
}
}
No need for #Bean declaration when you have #Component/#Service/#Repository
#Configuration
public class AppConfig { //other stuff here not duplicated beans }
And your main class
package com.app;
#SpringBootApplication // contains #EnableAutoConfiguration #ComponentScan #Configuration
public class App {
#Autowired
private Service service;
public static void main(String[] args) {
final SpringApplication app = new SpringApplication(App.class);
//app.setShowBanner(false);
app.run();
}
#PostConstruct
public void foo() {
System.out.println("Instantiated service name = " + service.serviceName);
}
}