Hopefully my question is fairly self-explanatory - I will illustrate it with some example code.
#Component
#PropertySource("classpath:/my-properties.properties")
public class SomeProperties {
#Autowired
Environment env;
// private methods
public boolean isEnabled(Foo foo) {
// call private methods, call env.getProperty, return value
}
}
#Component // it makes no difference whether it's there or not
public class MyCondition implements Condition {
#Autowired // doesn't make a difference
private SomeProperties someProperties;
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// ...
boolean b = someProperties.isEnabled(foo); // get NPE on this line
// ...return
}
}
#Component
#Conditional(MyCondition.class)
public class Bar {
// stuff
}
(Here I'm using Spring Boot to configure Spring. Although I doubt it makes any difference - as #Component beans are definitely accessible post-bootstrap, so it doesn't seem to be a problem in the way Spring is configured.)
The problem is that I'm getting a NullPointerException on the indicated line, because someProperties is null. This is presumably because at the time that the condition is run, the autowiring/instantiation phase of Spring bootstrap has not happened yet.
Is there any way to access Spring Properties in this way - like force Spring to load a bean before it normally would? Or is the only way to use standard Java / Apache Commons properties code as opposed to Spring?
Related
Spring cache is not working when calling cached method from another method of the same bean.
Here is an example to explain my problem in clear way.
Configuration:
<cache:annotation-driven cache-manager="myCacheManager" />
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="myCache" />
</bean>
<!-- Ehcache library setup -->
<bean id="myCache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
<cache name="employeeData" maxElementsInMemory="100"/>
Cached service :
#Named("aService")
public class AService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = getEmployeeData(date);
...
}
}
Result :
aService.getEmployeeData(someDate);
output: Cache is not being used
aService.getEmployeeData(someDate);
output:
aService.getEmployeeEnrichedData(someDate);
output: Cache is not being used
The getEmployeeData method call uses cache employeeData in the second call as expected. But when the getEmployeeData method is called within the AService class (in getEmployeeEnrichedData), Cache is not being used.
Is this how spring cache works or am i missing something ?
I believe this is how it works. From what I remember reading, there is a proxy class generated that intercepts all requests and responds with the cached value, but 'internal' calls within the same class will not get the cached value.
From https://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
Only external method calls coming in through the proxy are
intercepted. This means that self-invocation, in effect, a method
within the target object calling another method of the target object,
will not lead to an actual cache interception at runtime even if the
invoked method is marked with #Cacheable.
Since Spring 4.3 the problem could be solved using self-autowiring over #Resource annotation:
#Component
#CacheConfig(cacheNames = "SphereClientFactoryCache")
public class CacheableSphereClientFactoryImpl implements SphereClientFactory {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
#Resource
private SphereClientFactory self;
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull TenantConfig tenantConfig) {
// 2. call cached method using self-bean
return self.createSphereClient(tenantConfig.getSphereClientConfig());
}
#Override
#Cacheable(sync = true)
public SphereClient createSphereClient(#Nonnull SphereClientConfig clientConfig) {
return CtpClientConfigurationUtils.createSphereClient(clientConfig);
}
}
The example below is what I use to hit the proxy from within the same bean, it is similar to #mario-eis' solution, but I find it a bit more readable (maybe it's not:-). Anyway, I like to keep the #Cacheable annotations at the service level:
#Service
#Transactional(readOnly=true)
public class SettingServiceImpl implements SettingService {
#Inject
private SettingRepository settingRepository;
#Inject
private ApplicationContext applicationContext;
#Override
#Cacheable("settingsCache")
public String findValue(String name) {
Setting setting = settingRepository.findOne(name);
if(setting == null){
return null;
}
return setting.getValue();
}
#Override
public Boolean findBoolean(String name) {
String value = getSpringProxy().findValue(name);
if (value == null) {
return null;
}
return Boolean.valueOf(value);
}
/**
* Use proxy to hit cache
*/
private SettingService getSpringProxy() {
return applicationContext.getBean(SettingService.class);
}
...
See also Starting new transaction in Spring bean
Here is what I do for small projects with only marginal usage of method calls within the same class. In-code documentation is strongly advidsed, as it may look strage to colleagues. But its easy to test, simple, quick to achieve and spares me the full blown AspectJ instrumentation. However, for more heavy usage I'd advice the AspectJ solution.
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class AService {
private final AService _aService;
#Autowired
public AService(AService aService) {
_aService = aService;
}
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = _aService.getEmployeeData(date);
...
}
}
If you call a cached method from same bean it will be treated as a private method and annotations will be ignored
Yes, the caching will not happen because of the reasons that were already mentioned in the other posts. However I would solve the problem by putting that method to its own class (service in this case). With that your code will be easier to maintain/test and understand.
#Service // or #Named("aService")
public class AService {
#Autowired //or how you inject your dependencies
private EmployeeService employeeService;
public List<EmployeeData> getEmployeeData(Date date){
employeeService.getEmployeeData(date);
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = getEmployeeData(date);
...
}
}
#Service // or #Named("employeeService")
public class EmployeeService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
println("This will be called only once for same date");
...
}
}
In my Case I add variable :
#Autowired
private AService aService;
So I call the getEmployeeData method by using the aService
#Named("aService")
public class AService {
#Cacheable("employeeData")
public List<EmployeeData> getEmployeeData(Date date){
..println("Cache is not being used");
...
}
public List<EmployeeEnrichedData> getEmployeeEnrichedData(Date date){
List<EmployeeData> employeeData = aService.getEmployeeData(date);
...
}
}
It will use the cache in this case.
Better approach should be creating another service like ACachingService and call ACachingService.cachingMethod() instead of self Autowiring ( or any other approach trying to self inject). This way you do not fall into Circular dependency, which may be resulted in warning/error when upgrade to newer Spring ( Spring 2.6.6 in my case ) :
ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'webSecurityConfig':
Requested bean is currently in creation: Is there an unresolvable circular reference?
We looked at all the solutions here and decided to use a separate class for the cached methods because Spring 5 doesn't like circular dependencies.
Use static weaving to create proxy around your bean. In this case even 'internal' methods would work correctly
I use internal inner bean (FactoryInternalCache) with real cache for this purpose:
#Component
public class CacheableClientFactoryImpl implements ClientFactory {
private final FactoryInternalCache factoryInternalCache;
#Autowired
public CacheableClientFactoryImpl(#Nonnull FactoryInternalCache factoryInternalCache) {
this.factoryInternalCache = factoryInternalCache;
}
/**
* Returns cached client instance from cache.
*/
#Override
public Client createClient(#Nonnull AggregatedConfig aggregateConfig) {
return factoryInternalCache.createClient(aggregateConfig.getClientConfig());
}
/**
* Returns cached client instance from cache.
*/
#Override
public Client createClient(#Nonnull ClientConfig clientConfig) {
return factoryInternalCache.createClient(clientConfig);
}
/**
* Spring caching feature works over AOP proxies, thus internal calls to cached methods don't work. That's why
* this internal bean is created: it "proxifies" overloaded {#code #createClient(...)} methods
* to real AOP proxified cacheable bean method {#link #createClient}.
*
* #see Spring Cache #Cacheable - not working while calling from another method of the same bean
* #see Spring cache #Cacheable method ignored when called from within the same class
*/
#EnableCaching
#CacheConfig(cacheNames = "ClientFactoryCache")
static class FactoryInternalCache {
#Cacheable(sync = true)
public Client createClient(#Nonnull ClientConfig clientConfig) {
return ClientCreationUtils.createClient(clientConfig);
}
}
}
I would like to share what I think is the easiest approach:
Autowire the controller and use to call the method it instead of using the class context this.
The updated code would look like:
#Controller
public class TestController {
#Autowired TestController self;
#RequestMapping("/test")
public String testView(){
self.expensiveMethod();
return "test";
}
#Cacheable("ones")
public void expensiveMethod(){
System.out.println("Cache is not being used");
}
}
The default advice mode for processing caching annotation is “proxy”. At the startup of an application, all the caching annotations like #Caching, #Cacheable, #CacheEvict etc. are scanned and a target proxy class is generated for all of these classes. The proxy allows for intercepting the calls to these cacheable methods, which adds the caching advice/behavior.
So when we invoke the cacheable methods from the same class, as shown below, calls from the clients don’t get intercepted in a way that allows for caching advice to be added to them. Hence, every single time there is an unexpected cache miss.
Solution: Invoke the Cacheable methods from a different bean to use proxy class with caching advice.
When trying to inject an Optional<T>, Spring never calls my bean, and instead injects an Optional.empty().
Here is some sample code:
#Configuration
public class Initialize {
#Value("optionalValue")
private String testString;
#Bean (name = "getOptionalString")
public Optional<String> getOptionalString() {
return Optional.of(this.testString); //breakpoint put here, is never called
}
}
#Component
public class Test {
public Test(#Qualifier("getOptionalString") Optional<String> optional) {
// optional's value is Optional.empty() here
}
I noticed that (by putting a breakpoint) the #Bean is never called. If I were to remove the Optional<String>, and simply return a String, then it works!
I know Spring has its own optional dependency but I am perplexed as to why this doesn't work (whatever I read online says it should), and I also don't understand how it initialized it to Optional.empty()?
The documentation says:
you can express the non-required nature of a particular dependency through Java 8’s java.util.Optional, as the following example shows:
public class SimpleMovieLister {
#Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
...
}
}
So using Optional as the type of a bean is not a good idea.
I am migrating my current app in Spring/J2EE to Lagom. I am working in Java. I need to read variables from the configuration (application.conf in resources folder). In the implementation module, I try to inject configuration as a class variable like this
#Inject
private Configuration config
but when I access this config object in the constructor, it gives null pointer exception.
The whole code is like this
import play.Configuration;
public class SomeServiceImpl implements SomeService {
#Inject
private Configuration config;
public SomeServiceImpl() {
//getting configuration from application.conf
// gives exception as config is null.
String key = config.getString(“key”);
}
#Override
public ServiceCall<Request, Response> send() {
//works here, does not give exception
String key = config.getString(“key”);
}
}
Sorry, I should have been clear from the beginning. I have edited the original question. I get null pointer exception when I try to read from configuration object in constructor but I am able to use it in service call implementation. I want some way in which I can access the configuration in application.conf at startup and possibly store in some config class which can be accessed anywhere later.
In Java, when an object is instantiated, the first thing that happens (before anything else can possibly happen) is the constructor is invoked. After that, frameworks like Guice (which Lagom uses) are free to inject things, but they can't do it until the constructor has been invoked. So, all your #Inject annotated fields will be null when the constructor is invoked, there is nothing you can do to work around that.
So, don't use field injection, use constructor injection, eg:
import play.Configuration;
public class SomeServiceImpl implements SomeService {
private final Configuration config;
#Inject
public SomeServiceImpl(Configuration config) {
this.config = config;
String key = config.getString("key");
}
#Override
public ServiceCall<Request, Response> send() {
String key = config.getString("key");
}
}
Constructor injection is not just recommended for this use case, you should be using it everywhere, it avoids all these potential issues.
I am trying to define a custom DeltaSpike ConfigSource. The custom config source will have the highest priority and check the database for the config parameter.
I have a ConfigParameter entity, that simply has a key and a value.
#Entity
#Cacheable
public class ConfigParameter ... {
private String key;
private String value;
}
I have a #Dependent DAO that finds all config parameters.
What I am trying to do now, is define a custom ConfigSource, that is able to get the config parameter from the database. Therefore, I want to inject my DAO in the ConfigSource. So basically something like
#ApplicationScoped
public class DatabaseConfigSource implements ConfigSource {
#Inject
private ConfigParameterDao configParameterDao;
....
}
However, when registering the ConfigSource via META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource, the class will be instantiated and CDI will not work.
Is there any way to get CDI working in this case?
Thanks in advance, if you need any further information, please let me know.
The main problem is, that the ConfigSource gets instantiated very early on when the BeanManager is not available yet. Even the JNDI lookup does not work at that point in time. Thus, I need to delay the injection/lookup.
What I did now, is add a static boolean to my config source, that I set manually. We have a InitializerService that makes sure that the system is setup properly. At the end of the initialization process, I call allowInitialization() in order to tell the config source, that the bean is injectable now. Next time the ConfigSource is asked, it will be able to inject the bean using BeanProvider.injectFields.
public class DatabaseConfigSource implements ConfigSource {
private static boolean allowInit;
#Inject
private ConfigParameterProvider configParameterProvider;
#Override
public int getOrdinal() {
return 500;
}
#Override
public String getPropertyValue(String key) {
initIfNecessary();
if (configParameterProvider == null) {
return null;
}
return configParameterProvider.getProperty(key);
}
public static void allowInitialization() {
allowInit = true;
}
private void initIfNecessary() {
if (allowInit) {
BeanProvider.injectFields(this);
}
}
}
I have a request-scoped bean that holds all my config variables for type-safe access.
#RequestScoped
public class Configuration {
#Inject
#ConfigProperty(name = "myProperty")
private String myProperty;
#Inject
#ConfigProperty(name = "myProperty2")
private String myProperty2;
....
}
When injecting the Configuration class in a different bean, each ConfigProperty will be resolved. Since my custom DatabaseConfigSource has the highest ordinal (500), it will be used for property resolution first. If the property is not found, it will delegate the resolution to the next ConfigSource.
For each ConfigProperty the getPropertyValue function from the DatabaseConfigSource is called. Since I do not want to retreive the parameters from the database for each config property, I moved the config property resolution to a request-scoped bean.
#RequestScoped
public class ConfigParameterProvider {
#Inject
private ConfigParameterDao configParameterDao;
private Map<String, String> configParameters = new HashMap<>();
#PostConstruct
public void init() {
List<ConfigParameter> configParams = configParameterDao.findAll();
configParameters = configParams.stream()
.collect(toMap(ConfigParameter::getId, ConfigParameter::getValue));
}
public String getProperty(String key) {
return configParameters.get(key);
}
}
I could sure change the request-scoped ConfigParameterProvider to ApplicationScoped. However, we have a multi-tenant setup and the parameters need to be resolved per request.
As you can see, this is a bit hacky, because we need to explicitly tell the ConfigSource, when it is allowed to be instantiated properly (inject the bean).
I would prefer a standarized solution from DeltaSpike for using CDI in a ConfigSource. If you have any idea on how to properly realise this, please let me know.
Even though this post has been answered already I'd like to suggest another possible solution for this problem.
I managed to load properties from my db service by creating an #Signleton #Startup EJB which extends the org.apache.deltaspike.core.impl.config.BaseConfigSource and injects my DAO as delegate which I then registered into the org.apache.deltaspike.core.api.config.ConfigResolver.
#Startup
#Singleton
public class DatabaseConfigSourceBean extends BaseConfigSource {
private static final Logger logger = LoggerFactory.getLogger(DatabaseConfigSourceBean.class);
private #Inject PropertyService delegateService;
#PostConstruct
public void onStartup() {
ConfigResolver.addConfigSources(Collections.singletonList(this));
logger.info("Registered the DatabaseConfigSourceBean in the ConfigSourceProvider ...");
}
#Override
public Map<String, String> getProperties() {
return delegateService.getProperties();
}
#Override
public String getPropertyValue(String key) {
return delegateService.getPropertyValue(key);
}
#Override
public String getConfigName() {
return DatabaseConfigSourceBean.class.getSimpleName();
}
#Override
public boolean isScannable() {
return true;
}
}
I know that creating an EJB for this purpose basically produces a way too big overhead, but I think it's a bit of a cleaner solution instead of handling this problem by some marker booleans with static accessors ...
DS is using the java se spi mechanism for this which is not CD'Injectable'. One solution would be to use the BeanProvider to get hold of your DatabaseConfigSource and delegate operations to it.
What would be a somewhat equivalent class for TransactionScope(.Net) in Spring.
I know absolutely nothing about .Net, so I'm not certain if this is what you're looking for. You can use SimpleTransactionScope in order to maintain objects across the lifecycle of a transaction. It is not registered by default, so you will have to register it with spring core like any custom scope, and give it a stringy name. Then if you want you can also create an annotation specifically to register one.
It was my issue that suggested this a few years ago, after this question was created for certain. We requested it specifically for timestamps across multiple methods for injection in a service. You can do something like this.
public class SimpleTransactionFactoryPostProcessor implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
factory.registerScope("transaction", new SimpleTransactionScope());
}
}
#Configuration
class MyConfiguration {
#Scope(scopeName = "transaction")
#Bean
Instant nowInstant() {
return Instant.now();
}
}
#Service
class MyService {
private final ObjectFactory<Instant> nowFactory;
MyService( #Qualifier("nowInstant") ObjectFactory<Instant> nowFactory ) {
this.nowFactory = nowfactory
}
#Transactional
public boolean nowisEqualAlways() {
var now = nowFactory.getObject();
var sameNow = nowFactory.getObject();
return Objects.equals( now, sameNow );
}
}
If you don't do this, your now could actually change during your transaction by a small amount of time. You can test that simply by spamming now calls in a test.
It may not be required for your needs, so it's hard for me to tell (obviously your needs are probably long past, hopeful.y this helps someone in the future though)
The #Transactional annotation looks equivalent.
This can be placed on classes and methods and can be defined with propagation, isolation, rollback etc.