Getting Annotated Spring bean in jsp - spring

I have problem in getting Spring bean from JSP. I have a Spring bean configured using annotation:
#Configuration
public class DefaultServiceConfiguration extends AbstractSpringConfiguration {
#Bean
public ExService exService() {
ExServiceImpl service = new ExServiceImpl();
return service;
}
}
And the ExServiceImpl is as below:
public ExServiceImpl implements ExService {
#Override
public String getApprove(Integer x) {
// .....
return approve;
}
}
Now, I want to acccess the Beans method in JSP:
<c:set var="clientApprove" scope="request" value="${ExService .getApprove(1)}"/>
But it is not working.

What you want to do is not good design at all, and you shall avoid it.
But I believe this will help you:
#Bean(scope=DefaultScopes.REQUEST, name="myBean")
public ExService exService() {
ExServiceImpl service = new ExServiceImpl();
return service;
}
But then the bean will not be singleton.

I think we should add #Service annotation above the ExServiceImpl class to create the bean Service
#Service
public ExServiceImpl implements ExService {
}

Related

Spring boot defining configuration beans per user

I am using Spring boot. I have some question regarding the spring boot beans.
But I have doubt
I use bean which are default scope that is singleton. So they will have only one instance per application.
#Configuration
public class ...{
#Bean
public void method() {}
}
And
Now i use bean which scope is prototype. So they will have each instance per request.
#Configuration
public class ...{
#Bean
#Scope("prototype")
public void method() {}
}
But
I want single instance per user..? all request use single instance per user.
#Configuration
class Abc {
#Bean
#Scope("session")
public YourBean getYourBean() {
return new YourBean();
}
}
You will need to define one singleton bean with a property using prototype bean:(xml example)
With #bean definition:
#Component
#Scope("singleton")
public class SingletonBean {
// ..
#Autowired
private PrototypeBean prototypeBean;
//..
}
#Component
#Scope("prototype")
public class PrototypeBean {
//.......
}
Example: https://www.baeldung.com/spring-inject-prototype-bean-into-singleton

Does registering bean inside #Component class respect #Scope?

This website says beans registered inside component classes are not cglib proxied and do not go through the spring container. So does this mean if I register a bean inside a component class (snippet below), adding #Scope("request") wont make any difference, and a new instance of AnotherBean will always be created whenever testBean.anotherBean() is called from some external class?
#Component
public class TestBean {
#Bean
#Scope("request")
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
The bean that is not cglib proxied is the #Component itself, not the bean registered using the #Bean annotation. If you are not calling the anotherBean method explicitly, it won't make a difference because the proxy is used to return the bean when the method annotated with #Bean is called. See the example
The bean testBeanComponent is not cglib proxied :
#Component
public class TestBeanComponent {
#Bean
#Scope("request")
public AnotherBeanComponent anotherBeanComponent() {
return new AnotherBeanComponent();
}
}
The bean testBeanConfiguration is cglib proxied :
#Configuration
public class TestBeanConfiguration {
#Bean
#Scope("request")
public AnotherBeanConfiguration anotherBeanConfiguration() {
return new AnotherBeanConfiguration();
}
}
What it mean :
#Service
public class TestService {
#Autowired //Inject a normal bean
private TestBeanComponent testBeanComponent;
#Autowired //Inject a proxy
private TestBeanConfiguration testBeanConfiguration;
public void test() {
//Calling anotherBeanComponent always return a new instance of AnotherBeanComponent
testBeanComponent.anotherBeanComponent()
.equals(testBeanComponent.anotherBeanComponent()); // is false
//Calling anotherBeanConfiguration return the bean managed by the container
testBeanConfiguration.anotherBeanConfiguration()
.equals(testBeanConfiguration.anotherBeanConfiguration()); // is true
}
}
But if you are injecting the bean instead of using the method, everything will work as you expected :
#Service
public class TestService2 {
#Autowired //Inject a proxy with scope request
private AnotherBeanComponent anotherBeanComponent;
#Autowired //Inject a proxy with scope request
private AnotherBeanConfiguration anotherBeanConfiguration;
}

how to avoid using context.getbean in spring

There have been several arguments around not using ApplicationContext.getBean() to get a bean reference, of which most are based on logic that it violates the principles of Inversion of control.
Is there a way to get reference to prototype scoped bean without calling context.getBean() ?
Consider to use Spring Boot!
Than you can do something like this...
Runner:
#SpringBootApplication
public class Runner{
public static void main(String[] args) {
SpringApplication.run(Runner.class, args);
}
}
Some Controller:
#Controller
public class MyController {
// Spring Boot injecting beans through #Autowired annotation
#Autowired
#Qualifier("CoolFeature") // Use Qualifier annotation to mark a class, if for example
// you have more than one concreate class with differant implementations of some interface.
private CoolFeature myFeature;
public void testFeature(){
myFeature.doStuff();
}
}
Some cool feature:
#Component("CoolFeature") // To identify with Qualifier
public class CoolFeature{
#Autowired
private SomeOtherBean utilityBean;
public void doStuff(){
// use utilityBean in some way
}
}
No XML files to handle.
We can still access context for manual configurations if needed.
Suggested reading:
Spring Boot Reference
Pro Spring Boot
This type of problem can be solved using method injection, which is described in more detail here: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-method-injection
This is the most common approach to create prototype bean:
abstract class MyService {
void doSome() {
OtherService otherService = getOtherService();
}
abstract OtherService getOtherService();
}
#Configuration
class Config {
#Bean
public MyService myService() {
return new MyService() {
OtherService getOtherService() {
return otherService();
}
}
}
#Bean
#Scope("prototype")
public OtherService otherService() {
return new OtherService();
}
}

Multiple Spring Configuration files (one per Profile)

I'm a Spring rookie and trying to benefit from the advantages of the easy 'profile' handling of Spring. I already worked through this tutorial: https://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile and now I'd like to adapt that concept to an easy example.
I've got two profiles: dev and prod. I imagine a #Configuration class for each profile where I can instantiate different beans (implementing a common interface respectively) depending on the set profile.
My currently used classes look like this:
StatusController.java
#RestController
#RequestMapping("/status")
public class StatusController {
private final EnvironmentAwareBean environmentBean;
#Autowired
public StatusController(EnvironmentAwareBean environmentBean) {
this.environmentBean = environmentBean;
}
#RequestMapping(method = RequestMethod.GET)
Status getStatus() {
Status status = new Status();
status.setExtra("environmentBean=" + environmentBean.getString());
return status;
}
}
EnvironmentAwareBean.java
public interface EnvironmentAwareBean {
String getString();
}
EnvironmentAwareBean.java
#Service
public class DevBean implements EnvironmentAwareBean {
#Override
public String getString() {
return "development";
}
}
EnvironmentAwareBean.java
#Service
public class ProdBean implements EnvironmentAwareBean {
#Override
public String getString() {
return "production";
}
}
DevConfig.java
#Configuration
#Profile("dev")
public class DevConfig {
#Bean
public EnvironmentAwareBean getDevBean() {
return new DevBean();
}
}
ProdConfig.java
#Configuration
#Profile("prod")
public class ProdConfig {
#Bean
public EnvironmentAwareBean getProdBean() {
return new ProdBean();
}
}
Running the example throws this exception during startup (SPRING_PROFILES_DEFAULT is set to dev):
(...) UnsatisfiedDependencyException: (...) nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [EnvironmentAwareBean] is defined: expected single matching bean but found 3: prodBean,devBean,getDevBean
Is my approach far from a recommended configuration? In my opinion it would make more sense to annotate each Configuration with the #Profile annotation instead of doing it for each and every bean and possibly forgetting some variants when new classes are added later on.
Your implementations of EnvironmentAwareBean are all annotated with #Service.
This means they will all be picked up by component scanning and hence you get more than one matching bean. Do they need to be annotated with #Service?
Annotating each #Configuration with the #Profile annotation is fine. Another way as an educational exercise would be to not use #Profile and instead annotate the #Bean or Config classes with your own implementation of #Conditional.

Why Spring #Autowired ApplicationContext appContext is null?

I have Spring bean with annotations:
#Named
#Scope("session")
And this bean property:
#Autowired
ApplicationContext appContext;
The Spring configuration file has entry (that works for other anotations/injections):
<context:component-scan base-package="my.package.name" />
Why appContext is null after such code and configuration?
I am trying to get ApplicationContext (to call getBean(...) on it) and this can be quite involved task (judging from other discussions) in previous Spring versions (e.g. one is required to get ServletContext in Spring web application to create ApplicationContext and getting ServletContext can be quite involved task for beans that don't directly access HTTP Request objects). In Spring 3.x, as I understand, simple #Autwired injection can be used. How AppContext can be accessed?
Here the first problem is you are using #Named which is Java EE annotation and as for as I know Spring yet to support Java EE annotations. Hence instead of using #Named try to use Spring annotation #Service, #Component, #Repository etc.
Here is the example for you I have used JSF Managed bean as well to show how to integrate beans.
#ManagedBean(name="myBacking")
#RequestScoped
public class MyBacking {
private String myText;
#ManagedProperty(value="#{mySpring}")
MySpringBean mySpring;
public String getMyText() {
myText = mySpring.getText();
return myText;
}
public void setMyText(String myText) {
this.myText = myText;
}
public MySpringBean getMySpring() {
return mySpring;
}
public void setMySpring(MySpringBean mySpring) {
this.mySpring = mySpring;
}
}
#Service("mySpring")
#Scope("request")
public class MySpringBean {
#Autowired
MySecond mySecond;
public String getText(){
return "Hello KP" + mySecond.appObj();
}
}
#Service
#Scope("request")
public class MySecond {
#Autowired
ApplicationContext applicationContext;
public String appObj(){
MyThrid mythird =(MyThrid)applicationContext.getBean("myThrid");
return "My Second Bean calld "+ mythird.getTxt();
}
}
#Service
public class MyThrid {
public String getTxt(){
return "from thrid Bean";
}
}

Resources