I have a class called Menu, annnotated as #Entity where i need to use a method inside a class called GestoreMessaggi
....
#Component
#Entity
#Table(name="menu")
public class Menu implements Serializable{
#Autowired
#Transient // because i dont' save this field on the DB
private GestoreMessaggi gestoreMessaggi;
.....
public void setCurrentLanguage(){
/* I got the error both if use gestoreMessaggi
this way and if I use the autowired istance of GestoreMessaggi*/
GestoreMessaggi gestoreMessaggi = new GestoreMessaggi();
gestoreMessaggi.gest();
}
.....
This is the relevant code of the class GestoreMessaggi
#Component
public class GestoreMessaggi {
#Autowired
private ReloadableResourceBundleMessageSource messageSource;
public void gest(){
messageSource.doSomething() <--- here messageSource is null
}
}
When, I call gestoreMessaggi.gest(); from Menu class, I got an error because messageSource is null. The gestoreMessaggi istance is NOT null, is null just messageSource
IMPORTANT: I get null on messageSource only when I call GestoreMessaggi from classes annotated as #Entity.
In ds-servlet.xml I tell Spring to scan the pakages that contain Menu and GestoreMessaggi classes:
//Menu package
<context:component-scan base-package="com.springgestioneerrori.model"/>
//Gestore messaggi package
<context:component-scan base-package="com.springgestioneerrori.internazionalizzazione"/>
Thank you
You can follow two approaches:
Try to get an instance of a Spring-managed bean from within a method of your #Entity class
Change the design as suggested by #Stijn Geukens and make your entity a POJO without any logic or dependency injection machanisms
If you go by option 1, you have to explicitly access Spring's context and retrieve an instance of the bean you need:
#Component
public class Spring implements ApplicationContextAware {
private static final String ERR_MSG = "Spring utility class not initialized";
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T bean(Class<T> clazz) {
if (context == null) {
throw new IllegalStateException(ERR_MSG);
}
return context.getBean(clazz);
}
public static <T> T bean(String name) {
if (context == null) {
throw new IllegalStateException(ERR_MSG);
}
return (T) context.getBean(name);
}
}
You need to make Spring scan this class in order for this to work.
Then, inside your #EntityClass, do this:
public void setCurrentLanguage(){
GestoreMessaggi gestoreMessaggi = Spring.bean(GestoreMessaggi.class);
gestoreMessaggi.gest();
}
And that would be all. Note that you wouldn't need to autowire GestoreMessaggi into your #Entity any more. Please also note that this approach is not recommended neither by Spring nor by most of the community, since it couples your domain classes (your #Entity class) to Spring classes.
If you go by option 2, then all you need to do is let Spring resolve the autowiring as usual, but outside of your entity (i.e. in a dao or service), and if your entity needs you to fill it with some message or whatever, just invoke a setter on it. (Then it's up to you to make your #Entitys attribute #Transient or not, depending on your requirements).
Spring context does not manage entities (in general does not manage objects instantiated using new), this is why you cannot autowire beans (that come from Spring's context) in entities.
Best practices suggest to keep only getter and setter in your entities, leaving the business logic to the service layer.
A common approach is Service <-> DAO <-> Entity. Example:
Service layer:
#Service
public interface GestoreMessaggi {
public void gest();
}
public class GestoreMessaggiImpl implements GestoreMessaggi {
#Autowired
private MenuDao menuDao;
#Override
public void gest() {
// 1) retrieve your entity instance with menuDao
// 2) do stuffs with your entity
// 3) maybe save your entity using menuDao
}
}
DAO layer:
If you use Spring Data Jpa:
public interface MenuDao extends JpaRepository<Menu, [menu-id-type]> {}
Else:
public interface MenuDao {
public Menu findOne([menu-id-type] id);
public Menu save(Menu menu);
// other methods for accessing your data
}
#Repository
public class MenuDaoImpl {
// inject EntityManager or Hibernate SessionFactory
// implement your DAO interface accessing your entities
}
Finally remember to configure Spring's beans including your #Services and your #Repositorys in your configuration (explicitly or by package scanning).
Using Spring MVC, you should inject (autowire) your #Services in a #Controller class, so the controller can call services methods, which call DAOs methods, which access your data.
Related
I am searching for a way to read and parse a lot of data when the spring boot app is starting and be able to use these data later in other classes.
I started with a class DataRepository.java and annotated it with #Service to be able to inject it later. I'm planning to read the data here and to inject it in any other class I need the data.
But how can I achieve to parse the data just once and at app startup? The spring boot app should only be reachable if the parsing is done.
Your approach with #Service is 100% appropriate.
By default all beans are singletons, so if you parse data on bean creation (in constructor) it will be parsed only once, and this info can be used in other beans by simple injection.
Please note that if during data parsing you have to use other beans, you should be confident that all beans are completely constructed. For that you should use approach proposed by #jreznot:
https://stackoverflow.com/a/51783858/5289288
You can use ContextStartedEvent and handle it:
#Component
public class ContextStartedListener implements ApplicationListener<ContextStartedEvent> {
#Override
public void onApplicationEvent(ContextStartedEvent cse) {
System.out.println("Handling context start event. ");
}
}
See also: https://www.baeldung.com/spring-events
By default all beans in spring context are singletons. Spring guarantees that it will creates a bean just ones during context loading.
For example if you will have few contexts in your application it creates one instance for every context.
If you have just one context you can use these approaches:
initialize data in constructor. Data will initialized and ready to
use just after bean's instance creation.
#Component
public class DataRepository {
public DataRepository() {
... init data
}
}
use #Bean annotation withinit method. Allows you don't stick to Spring in
your data repository and initialize data after all beans were created.
public class DataRepository {
public void init() {
... init data
}
}
#Configuration
public class DataRepositoryConfiguration {
#Bean(initMethod = "init")
public DataRepository dataRepository() {
return new DataRepository();
}
use #Bean annotation and invoke init method. Allows you don't stick to
Spring in your data repository, but #Autowired field will uninitialized.
public class DataRepository {
public void init() {
... init data
}
}
#Configuration
public class DataRepositoryConfiguration {
#Bean
public DataRepository dataRepository() {
DataRepository dr = new new DataRepository();
dr.init();
return dr;
}
}
use #PostConstruct annotation. Initialize data after all beans was
created.
public class DataRepository {
#PostConstruct
public void init() {
... init data
}
}
Exception thrown during initializing will stop Spring's context initializing
You can use PostConstruct on any bean. For example
#Component
class DataLoad {
......
......
#PostConstruct
public void parseData() {
...... do your stuff here.......
}
}
With this the code inside parseData will be called only once. This is a very common way to do things in scenarios like when you want to load some configuration data from database at the start of the application and do it only once. In these cases you can #Autowired the repository class to the same class and use that in your #PostConstruct method and get data
In a java-spring web-app I would like to be able to dynamically inject beans.
For example I have an interface with 2 different implementations:
In my app I'm using some properties file to configure injections:
#Determines the interface type the app uses. Possible values: implA, implB
myinterface.type=implA
My injections actually loaded conditionally relaying on the properties values in the properties file. For example in this case myinterface.type=implA wherever I inject MyInterface the implementation that will be injected will be ImplA (I accomplished that by extending the Conditional annotation).
I would like that during runtime - once the properties are changed the following will happen (without server restart):
The right implementation will be injected. For example when setting myinterface.type=implB ImplB will be injected where-ever MyInterface is used
Spring Environment should be refreshed with the new values and re-injected as well to beans.
I thought of refreshing my context but that creates problems.
I thought maybe to use setters for injection and re-use those setters once properties are re-configured. Is there a working practice for such a requirement?
Any ideas?
UPDATE
As some suggested I can use a factory/registry that holds both implementations (ImplA and ImplB) and returns the right one by querying the relevant property.
If I do that I still have the second challenge - the environment. for example if my registry looks like this:
#Service
public class MyRegistry {
private String configurationValue;
private final MyInterface implA;
private final MyInterface implB;
#Inject
public MyRegistry(Environmant env, MyInterface implA, MyInterface ImplB) {
this.implA = implA;
this.implB = implB;
this.configurationValue = env.getProperty("myinterface.type");
}
public MyInterface getMyInterface() {
switch(configurationValue) {
case "implA":
return implA;
case "implB":
return implB;
}
}
}
Once property has changed I should re-inject my environment. any suggestions for that?
I know I can query that env inside the method instead of constructor but this is a performance reduction and also I would like to think of an ider for re-injecting environment (again, maybe using a setter injection?).
I would keep this task as simple as possible. Instead of conditionally load one implementation of the MyInterface interface at startup and then fire an event that triggers dynamic loading of another implementation of the same interface, I would tackle this problem in a different way, that is much simpler to implement and maintain.
First of all, I'd just load all possible implementations:
#Component
public class MyInterfaceImplementationsHolder {
#Autowired
private Map<String, MyInterface> implementations;
public MyInterface get(String impl) {
return this.implementations.get(impl);
}
}
This bean is just a holder for all implementations of the MyInterface interface. Nothing magic here, just common Spring autowiring behavior.
Now, wherever you need to inject a specific implementation of MyInterface, you could do it with the help of an interface:
public interface MyInterfaceReloader {
void changeImplementation(MyInterface impl);
}
Then, for every class that needs to be notified of a change of the implementation, just make it implement the MyInterfaceReloader interface. For instance:
#Component
public class SomeBean implements MyInterfaceReloader {
// Do not autowire
private MyInterface myInterface;
#Override
public void changeImplementation(MyInterface impl) {
this.myInterface = impl;
}
}
Finally, you need a bean that actually changes the implementation in every bean that has MyInterface as an attribute:
#Component
public class MyInterfaceImplementationUpdater {
#Autowired
private Map<String, MyInterfaceReloader> reloaders;
#Autowired
private MyInterfaceImplementationsHolder holder;
public void updateImplementations(String implBeanName) {
this.reloaders.forEach((k, v) ->
v.changeImplementation(this.holder.get(implBeanName)));
}
}
This simply autowires all beans that implement the MyInterfaceReloader interface and updates each one of them with the new implementation, which is retrieved from the holder and passed as an argument. Again, common Spring autowiring rules.
Whenever you want the implementation to be changed, you should just invoke the updateImplementations method with the name of the bean of the new implementation, which is the lower camel case simple name of the class, i.e. myImplA or myImplB for classes MyImplA and MyImplB.
You should also invoke this method at startup, so that an initial implementation is set on every bean that implements the MyInterfaceReloader interface.
I solved a similar issue by using org.apache.commons.configuration.PropertiesConfiguration and org.springframework.beans.factory.config.ServiceLocatorFactoryBean:
Let VehicleRepairService be an interface:
public interface VehicleRepairService {
void repair();
}
and CarRepairService and TruckRepairService two classes that implements it:
public class CarRepairService implements VehicleRepairService {
#Override
public void repair() {
System.out.println("repair a car");
}
}
public class TruckRepairService implements VehicleRepairService {
#Override
public void repair() {
System.out.println("repair a truck");
}
}
I create an interface for a service factory:
public interface VehicleRepairServiceFactory {
VehicleRepairService getRepairService(String serviceType);
}
Let use Config as configuration class:
#Configuration()
#ComponentScan(basePackages = "config.test")
public class Config {
#Bean
public PropertiesConfiguration configuration(){
try {
PropertiesConfiguration configuration = new PropertiesConfiguration("example.properties");
configuration
.setReloadingStrategy(new FileChangedReloadingStrategy());
return configuration;
} catch (ConfigurationException e) {
throw new IllegalStateException(e);
}
}
#Bean
public ServiceLocatorFactoryBean serviceLocatorFactoryBean() {
ServiceLocatorFactoryBean serviceLocatorFactoryBean = new ServiceLocatorFactoryBean();
serviceLocatorFactoryBean
.setServiceLocatorInterface(VehicleRepairServiceFactory.class);
return serviceLocatorFactoryBean;
}
#Bean
public CarRepairService carRepairService() {
return new CarRepairService();
}
#Bean
public TruckRepairService truckRepairService() {
return new TruckRepairService();
}
#Bean
public SomeService someService(){
return new SomeService();
}
}
By using FileChangedReloadingStrategy your configuration be reload when you change the property file.
service=truckRepairService
#service=carRepairService
Having the configuration and the factory in your service, let you can get the appropriate service from the factory using the current value of the property.
#Service
public class SomeService {
#Autowired
private VehicleRepairServiceFactory factory;
#Autowired
private PropertiesConfiguration configuration;
public void doSomething() {
String service = configuration.getString("service");
VehicleRepairService vehicleRepairService = factory.getRepairService(service);
vehicleRepairService.repair();
}
}
Hope it helps.
If I understand you correctly then the goal is not to replace injected object instances but to use different implementations during interface method call depends on some condition at run time.
If it is so then you can try to look at the Sring TargetSource mechanism in combination with ProxyFactoryBean. The point is that proxy objects will be injected to beans that uses your interface, and all the interface method calls will be sent to TargetSource target.
Let's call this "Polymorphic Proxy".
Have a look at example below:
ConditionalTargetSource.java
#Component
public class ConditionalTargetSource implements TargetSource {
#Autowired
private MyRegistry registry;
#Override
public Class<?> getTargetClass() {
return MyInterface.class;
}
#Override
public boolean isStatic() {
return false;
}
#Override
public Object getTarget() throws Exception {
return registry.getMyInterface();
}
#Override
public void releaseTarget(Object target) throws Exception {
//Do some staff here if you want to release something related to interface instances that was created with MyRegistry.
}
}
applicationContext.xml
<bean id="myInterfaceFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="MyInterface"/>
<property name="targetSource" ref="conditionalTargetSource"/>
</bean>
<bean name="conditionalTargetSource" class="ConditionalTargetSource"/>
SomeService.java
#Service
public class SomeService {
#Autowired
private MyInterface myInterfaceBean;
public void foo(){
//Here we have `myInterfaceBean` proxy that will do `conditionalTargetSource.getTarget().bar()`
myInterfaceBean.bar();
}
}
Also if you want to have both MyInterface implementations to be Spring beans, and the Spring context could not contains both instances at the same time then you can try to use ServiceLocatorFactoryBean with prototype target beans scope and Conditional annotation on target implementation classes. This approach can be used instead of MyRegistry.
P.S.
Probably Application Context refresh operation also can do what you want but it can cause other problems such as performance overheads.
This may be a duplicate question or at least very similar, anyway I answered this sort of question here: Spring bean partial autowire prototype constructor
Pretty much when you want a different beans for a dependency at run-time you need to use a prototype scope. Then you can use a configuration to return different implementations of the prototype bean. You will need to handle the logic on which implementation to return yourself, (they could even be returning 2 different singleton beans it doesn't matter) But say you want new beans, and the logic for returning the implementation is in a bean called SomeBeanWithLogic.isSomeBooleanExpression(), then you can make a configuration:
#Configuration
public class SpringConfiguration
{
#Bean
#Autowired
#Scope("prototype")
public MyInterface createBean(SomeBeanWithLogic someBeanWithLogic )
{
if (someBeanWithLogic .isSomeBooleanExpression())
{
return new ImplA(); // I could be a singleton bean
}
else
{
return new ImplB(); // I could also be a singleton bean
}
}
}
There should never be a need to reload the context. If for instance, you want the implementation of a bean to change at run-time, use the above. If you really need to reload your application, because this bean was used in constructors of a singleton bean or something weird, then you need to re-think your design, and if these beans are really singleton beans. You shouldn't be reloading the context to re-create singleton beans to achieve different run-time behavior, that is not needed.
Edit The first part of this answer answered the question about dynamically injecting beans. As asked, but I think the question is more of one: 'how can I change the implementation of a singleton bean at run-time'. This could be done with a proxy design pattern.
interface MyInterface
{
public String doStuff();
}
#Component
public class Bean implements MyInterface
{
boolean todo = false; // change me as needed
// autowire implementations or create instances within this class as needed
#Qualifier("implA")
#Autowired
MyInterface implA;
#Qualifier("implB")
#Autowired
MyInterface implB;
public String doStuff()
{
if (todo)
{
return implA.doStuff();
}
else
{
return implB.doStuff();
}
}
}
You can use #Resource annotation for injection as originally answered here
e.g.
#Component("implA")
public class ImplA implements MyInterface {
...
}
#Component("implB")
public class ImplB implements MyInterface {
...
}
#Component
public class DependentClass {
#Resource(name = "\${myinterface.type}")
private MyInterface impl;
}
and then set the implementation type in properties file as -
myinterface.type=implA
Be aware that - if interesting to know about - FileChangedReloadingStrategy makes your project highly dependent on the deployment conditions: the WAR/EAR should be exploded by container and your should have direct access to the file system, conditions that are not always met in all situations and environments.
You can use Spring #Conditional on a property value. Give both Beans the same name and it should work as only one Instance will be created.
Have a look here on how to use #Conditional on Services and Components:
http://blog.codeleak.pl/2015/11/how-to-register-components-using.html
public abstract class SystemService {
}
public class FooSystemService extends FileSystemService {
}
public class GoSystemService extends FileSystemService {
}
#Configuration
public class SystemServiceConf {
#Bean
#Conditional(SystemServiceCondition.class)
public SystemService systemService(#Value("${value.key}") value) {
switch (value) {
case A:
return new FooSystemService();
case B:
return new GoSystemService();
default:
throw new RuntimeException("unknown value ");
}
}
}
public class SystemServiceCondition implements Condition {
#Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}
I try to use #Configurable to inject spring bean in #PostPersist listener.
#Configurable
#EnableSpringConfigured
public class BankAccountAuditListener {
#PersistenceContext
private EntityManager em;
#PostPersist
public void createAudit(BankAccount bankAccount){
...
}
}
Listener is called by #EntityListeners({BankAccountAuditListener.class})
I put this in spring configuration xml-file:
<context:annotation-config/>
<context:spring-configured/>
<context:load-time-weaver/>
In createAudit(...) function, em is always null.
What am I missing?
Ok, BankAccountAuditListener is created by Hibernate BEFORE ApplicationContext of spring is ready to use. Possibly this is the reason I can't inject there nothing.
You can use a lazily initialized bean inside your JPAEventListener class , which is initialized when the first time entity is persisted.
Then use #Configurable on lazy loaded bean.
It may not be the best solution but a quick workaround
public class JPAEntityListener{
/**
* Hibernate JPA EntityListEner is not spring managed and gets created via reflection by hibernate library while entitymanager is loaded.
* Inorder to inject business rules via Spring use lazy loaded bean which makes use of #Configurable
*/
private CustomEntityListener listener;
public JPAEntityListener() {
super();
}
#PrePersist
public void onEntityPrePersist(TransactionalEntity entity) {
if (listener == null) {
listener = new CustomEntityListener();
}
listener.onEntityPrePersist(entity);
}
#PreUpdate
public void onEntityPreUpdate(TransactionalEntity entity) {
if (listener == null) {
listener = new CustomEntityListener();
}
listener.onEntityPreUpdate(entity);
}}
And your lazy loaded bean class
#Configurable(autowire = Autowire.BY_TYPE)
public class CustomEntityListener{
#Autowired
private Environment environment;
public void onEntityPrePersist(TransactionalEntity entity) {
//custom logic
}
I am using Spring 3 and Hibernate 4
How can I use the following in a non ManagedBean
#Inject
EmployeeService employeeService
Or if I would want to access DAO method I have to make that a ManagedBean as
#Named("mymanagedbean")
#ViewAccessScoped
I have a few Converter class and in order to access DAO service methods I had to use that as ManagedBean even though they are not ManagedBeans.
What is the best approach to call DAO service methods?
Thanks
You will need to implement the Spring interface ApplicationContextAware and then set the ApplicationContext. Then you need provide static methods to get the bean instance.
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext context)
throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) { ...}
public static <T> T getBean(Class<T> arg0) {...}
Then in your non-managed bean you can call SpringApplicationContext.getBean method by passing in EmployeeService.class as the argument or the bean name as the argument.
If you want to keep your Converter class clean and use dependency injection (which is highly recommended in order to be able the test the class easily) instead of the class pulling in its dependencies manually, you can use Spring's ability to configure a pre-existing object created outside of the application context. See the related section in Spring's reference documentation here.
Here is a working example (pertinent to zagyi's answer). Application uses Spring Roo and therefore aspectj.
#FacesConverter("example.entity.converter")
#Configurable
public class EntityConverter implements Converter {
#Resource
MyDAO dao;
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
Entity obj;
try {
obj = dao.getEntity(Long.valueOf(value));
} catch( NumberFormatException e ) {
throw new ConverterException( message );
}
return obj;
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
Entity obj = (Entity) value;
return (obj != null) ? obj.getId().toString() : "";
}
}
The dao class
#Repository("myDAO")
public class MyDAOImpl implements MyDAO {
...
}
I have managed to get the DAO method in Converter without #Inject using the following and in EmployeeService class which implements Interface I have defined as #Service(value="employeeService")
EmployeeService employeeService =
(EmployeeService)facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null,
"employeeService");
Please bear with me:
We have a setup of Hibernate and Spring IoC, in which for each entity (User, Customer, Account, Payment, Coupon, etc) there's a bunch of "singleton" interfaces and implementation classes that support it.
For example: forCustomer:
#Entity
public class Customer extends BaseEntity {
...
public name();
}
/* base API */
public interface Service {
public create();
public list();
public find();
public update();
public delete();
}
/* specific API */
public interface CustomerService extends Service {
public findByName();
}
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
...
}
And this pattern goes on and on (CustomerManager, CustomerDataProvider, CustomerRenderer, etc.).
finally, in order work against an instance of a specific API (e.g. CustomerService.findByName()), a static global holder had evolved - which makes references like the following available:
public class ContextHolder {
private static AbstractApplicationContext appContext;
public static final CustomerService getCustomerService() {
return appContext.getBean(CustomerService.class);
}
//... omitting methods for each entity class X supporting class
}
#Configuration
public class ServicesConfiguration {
#Bean(name = "customerService")
#Lazy(false)
public CustomerService CustomerService() {
return new CustomerServiceImpl();
}
//... omitting methods for each entity class X supporting class
}
So, the question is:
what would be the proper way to inject those supporting classes, e.g. CustomerService, given an entity instance, for the following uses:
I have a specific entity (e.g. a Customer), and would like to get a service and call a specific API (e.g. findByName())?
I have an entity (don't care which one in specific), and would like to call a general API (e.g. find())
All this, while avoiding global static references (and thus, swap implementations in e.g. tests, and simplify the caller code).
So i can get a any supporting class if I have an entity instance
BaseEntity entity = ... // not injected
Iservice service = ...// should be injected
service.create(entity);
or, get all the supporting classes I need for a given entity type
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
// inject specific supporting classes
#Autowire CustomerManager manager;
#Autowire CustomerDataProvider provider;
#Autowire CustomerRenderer renderer;
#Autowire CustomerHelper helper;
...
}
and, change the configuration a bit in other scenarios
// how to configure Spring to inject this double?
Class CustomerManagerDouble extends CustomerManager {...}
#Autowired #Test public void testSpecificAPI(CustomerService service) {
service.doSomethingSpecific();
assert ((CustomerManagerDouble) service.getManager()).checkSomething();
}
I'm not entirely sure what you're asking, but I think you want to inject entity objects (created by Hibernate) with services, right?
If that's the case, use the #Configurable annotation as described in the Spring 3.1 documentation:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-atconfigurable
Note that you have to use AspectJ to weave the entity classes (load-time or compile-time) for this to work.