EJB3 Client Lookup - websphere

I am trying to invoke a EJB from a standalone Java client, getting the below error.
Lookup code
String localJNDIName = "ejbremote:gcmsnew/gcmsutilbeans.jar/CustomerSurveyManageQstBean#com.smbcgroup.gcms.utility.bl.survey.CustomerSurveyManageQstRemote";
InitialContext ic = new InitialContext();
GCMSBaseRemote bean = (GCMSBaseRemote)ic.lookup(localJNDIName);
Exception
javax.naming.ConfigurationException: NamingManager.getURLContext
cannot find the factory for this scheme: ejbremote at
com.ibm.ws.naming.jndicos.CNContextImpl.checkForUrlContext(CNContextImpl.java:471)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:160) at
com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179) at
javax.naming.InitialContext.lookup(Unknown Source) at
com.test.EJBClientTest.main(EJBClientTest.java:18)
Environment
RAD 7.5, EJB3. Websphere Application Server 7.0.

The ejbremote scheme does not exist in WebSphere Application Server (even though "ejblocal" does exist). Try using a ejb/ prefix instead of ejbremote:.
For more information, see the EJB application bindings overview topic in the InfoCenter.

Since this is a standalone ("thin") client may be you should try something like this:
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
properties.setProperty(Context.PROVIDER_URL,"corbaloc:iiop:localhost:2809"); //localhost=the host where your EJB is located, 2809=BOOTSTRAP_ADDRESS port
Context initCtx = new InitialContext(properties);
Object homeObject = initCtx.lookup("com.smbcgroup.gcms.utility.bl.survey.CustomerSurveyManageQstRemote"); //by default the JNDI name of your Remote Interface is its full class name
// Narrow to a real object
csmo = (CustomerSurveyManageQstRemote) javax.rmi.PortableRemoteObject.narrow(homeObject, com.smbcgroup.gcms.utility.bl.survey.CustomerSurveyManageQstRemote.class);
You should also have the appropriate Websphere Jars in your classpath in order to make the above calls.

For remote lookup
import java.io.IOException;
import java.util.Hashtable;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ServiceLocator {
static String url = "corbaloc:iiop:localhost:2809";
static String initial = "com.ibm.websphere.naming.WsnInitialContextFactory";
static String jndi = "ejb/enterprise_app_name/ejb_web_project_name.jar/ejb_name#name.of.remote.impl.interface";
private static ServiceLocator serviceLocator = null;
InitialContext context = null;
private ServiceLocator() throws NamingException, IOException {
Hashtable<String,String> env = new Hashtable<String,String> ();
env.put("java.naming.provider.url", url );
env.put("java.naming.factory.initial", initial );
context = new InitialContext(env);
}
public synchronized static ServiceLocator getInstance() throws NamingException, IOException {
if (serviceLocator == null) {
serviceLocator = new ServiceLocator();
}
return serviceLocator;
}
public Object getService(String jndiName) throws NamingException {
return context.lookup(jndiName);
}
public <T>T getRemoteObject(Class<T> remoteInterfaceClass) {
try {
return (T)javax.rmi.PortableRemoteObject.narrow( context.lookup(jndi), remoteInterfaceClass);
} catch (NamingException nexc) {
nexc.printStackTrace();
}
return null;
}
}
For local lookup
import java.io.IOException;
import java.util.Hashtable;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ServiceLocator {
static String url = "iiop://localhost";
static String initial = "com.ibm.websphere.naming.WsnInitialContextFactory";
static String jndi = "ejblocal:enterprise_app_name/ejb_web_project_name.jar/ejb_name#name.of.local.impl.interface";
private static ServiceLocator serviceLocator = null;
InitialContext context = null;
private ServiceLocator() throws NamingException, IOException {
Hashtable<String,String> env = new Hashtable<String,String> ();
env.put("java.naming.provider.url", url );
env.put("java.naming.factory.initial", initial );
context = new InitialContext(env);
}
public synchronized static ServiceLocator getInstance() throws NamingException, IOException {
if (serviceLocator == null) {
serviceLocator = new ServiceLocator();
}
return serviceLocator;
}
public Object getService(String jndiName) throws NamingException {
return context.lookup(jndiName);
}
public Object getService() throws NamingException {
return context.lookup(jndi);
}
}

You need to have the stub file to invoke the EJB, so first generate the stub file. In websphere there is utility available in the appserver bin folder createEJBStubs.

Related

Require a service to be active before a bundle is started

I have written a BundleActivator which should update certain configurations before its bundle starts. I need the ConfigurationAdmin service, but I get a null ServiceReference from the BundleContext in the start method of the BundleActivator.
The BundleActivator extends following abstract class and only implements the specific update logic:
public abstract class AbstractConfigUpdater implements BundleActivator {
private ServiceReference<ConfigurationAdmin> configurationAdminServiceReference;
#Override
public void start(final BundleContext context) throws Exception {
configurationAdminServiceReference = context.getServiceReference(ConfigurationAdmin.class);
final ConfigurationAdmin configurationAdmin = context.getService(configurationAdminServiceReference);
final Configuration[] configurations =
configurationAdmin.listConfigurations(getFilter());
if (configurations != null) {
for (final Configuration configuration : configurations) {
final Dictionary<String, Object> properties = configuration.getProperties();
if (updateProperties(properties)) {
configuration.update(properties);
}
}
}
}
protected abstract String getFilter();
/**
* Updates the properties if needed.
*
* #param properties
* the configuration properties
* #return if any modifications to the Dictionary were made
*/
protected abstract boolean updateProperties(final Dictionary<String, Object> properties);
#Override
public void stop(final BundleContext context) throws Exception {
context.ungetService(configurationAdminServiceReference);
}
}
I have added an annotation to the concrete BundleActivator to generate a manifest header to require the ConfigurationAdmin service to be available to the bundle:
#RequireCapability(filter = "(objectClass=org.osgi.service.cm.ConfigurationAdmin)",
ns = "osgi.service",
resolution = Resolution.mandatory)
The manifest header is generated, but I still get a null ServiceReference. How should I fix this? Or is there an alternative approach I could take to update configurations before their components are started?
I don't know if this could help, but you can develop a org.osgi.service.cm.ConfigurationPlugin to intercept all the properties that are injected at runtime and modify them:
public class MyConfigurationPlugin implements BundleActivator, ConfigurationPlugin {
ServiceRegistration<ConfigurationPlugin> configPluginRef;
#Override
public void start(BundleContext context) throws Exception {
//... init the config plugin
Map<String,String> properties = new HashMap<>();
configPluginRef = context.registerService(
ConfigurationPlugin.class,
this,
new Hashtable<>(properties));
}
#Override
public void modifyConfiguration(ServiceReference<?> reference,
Dictionary<String, Object> properties) {
/*
* View and possibly modify a set of configuration properties
* before they are sent to the Managed Service or the Managed Service Factory.
*/
}
}
Of course the Declarative Service approach is a way far simpler option:
#Component (
service= {},
configurationPid={
configPid1,
configPid2,
...
})
public class MyComponent {
#Activate
public void activate(BundleContext context, Map<String, String> properties) {
}
#Modified
public void updated(BundleContext context, Map<String, String> properties) {
// Called when properties change
}
}
but in this case you cannot alter properties values: you can only react to properties changes.
You can use OSGi ServiceTracker to wait and retrieve the service from the service registry.
For example,
import org.osgi.framework.Constants
import org.osgi.framework.Filter;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.service.cm.ConfigurationAdmin;
...
private static final long TIMEOUT_MILLIS = 10000;
#Override
public void start(final BundleContext context) throws Exception {
Filter filter = context.createFilter("(" + Constants.OBJECTCLASS + "=org.osgi.service.cm.ConfigurationAdmin)");
ServiceTracker<?, ?> configurationAdminTracker = new ServiceTracker<>(context, filter, null);
configurationAdminTracker.open();
ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) configurationAdminTracker.waitForService(TIMEOUT_MILLIS);
configurationAdminTracker.close();
if (configurationAdmin == null) {
// Not found
}
...
}

AWS lambda spring . Not able to load properties file

I have problem with loading the properties file where i reference the values from. Locally I am able to run it as expected. But AWS lambda function does not seem to work as expected since it is not able to laod properties file. Below is the handler written. I deploy MainHanlder.java function on lambda.
#Component
public class TestHandler implements RequestHandler<SNSEvent, Object> {
#Override
public String handleRequest(SNSEvent snsEvent, Context context) {
TestClient testClient = Application.getBean("pp",TestClient);
return null;
}
}
MainHandler.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
import com.test.lambda.ApplicationConfiguration;
public class MainHandler extends SpringRequestHandler<SNSEvent, Object> {
/**
* Here we create the Spring {#link ApplicationContext} that will
* be used throughout our application.
*/
private static final ApplicationContext context =
new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
#Override
public ApplicationContext getApplicationContext() {
return context;
}
}
SpringRequestHandler.java
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.springframework.context.ApplicationContext;
#SuppressWarnings("unchecked")
public abstract class SpringRequestHandler<I, O> implements RequestHandler<I, O>, ApplicationContextProvider {
private final RequestHandler<I, O> handler;
public SpringRequestHandler() {
handler = getApplicationContext().getBean(RequestHandler.class);
}
#Override
public O handleRequest(final I input, final Context context) {
return (O) handler.handleRequest(input, context);
}
}
Application.java
public class Application {
private static final AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext();
private static boolean flag = Boolean.TRUE;
private static final XLogger logger = XLoggerFactory.getXLogger(Application.class);
public static <T> T getBean(String env, Class<T> clazz) {
InputStream i1 = null;
InputStream i2 = null;
if(flag) {
Properties rp = new Properties();
Properties ap = new Properties();
try {
System.out.println("print env " + env);
i1 = Application.class.getResourceAsStream(“/application-” + env + ".properties");
rp.load(i1);
i2 = Application.class.getResourceAsStream("/application-" + env + ".properties");
ap.load(i2);
PropertyPlaceholderConfigurer propertyOverrideConfigurer = new PropertyPlaceholderConfigurer();
propertyOverrideConfigurer.setPropertiesArray(new Properties[]{rp,ap});
springContext.scan(new String[]{"com.pinto.lambda"});
springContext.addBeanFactoryPostProcessor(propertyOverrideConfigurer);
try {
springContext.refresh();
}catch(IllegalStateException e) {
}
flag = Boolean.FALSE;
} catch (Exception e) {
logger.error("Exception in the Application - " +e.getMessage());
throw new RuntimeException("Unable to load properties " + e.getMessage());
}
return springContext.getBean(clazz);
}
ERROR TRACE - AWS CONSOLE LOGS
==================== FUNCTION OUTPUT ====================
{"errorMessage":"Unable to load properties null","errorType":"java.lang.RuntimeException","stackTrace":["com.pinto.lambda.Application.getBean(Application.java:65)","com.pinto.lambda.handler.GetWarehouseInventoryHandler.handleRequest(TestHandler.java:44)","com.pinto.lambda.handler.GetWarehouseInventoryHandler.handleRequest(TestHandler.java:1)","com.pinto.lambda.handler.SpringRequestHandler.handleRequest(SpringRequestHandler.java:19)"]}
==================== FUNCTION LOG OUTPUT ====================
print env pp
[ERROR] Exception in the Application - null
Unable to load properties null: java.lang.RuntimeException
java.lang.RuntimeException: Unable to load properties null
at com.pinto.lambda.Application.getBean(Application.java:65)
at com.pinto.lambda.handler.TestHandler.handleRequest(TestHandler.java:44)
at com.pinto.lambda.handler.TestHandler.handleRequest(TestHandler.java:1)
at com.pinto.lambda.handler.SpringRequestHandler.handleRequest(SpringRequestHandler.java:19)

How to use Apache CachingHttpAsyncClient with Spring AsyncRestTemplate?

Is it possible to use CachingHttpAsyncClient with AsyncRestTemplate? HttpComponentsAsyncClientHttpRequestFactory expects a CloseableHttpAsyncClient but CachingHttpAsyncClient does not extend it.
This is known as issue SPR-15664 for versions up to 4.3.9 and 5.0.RC2 - fixed in 4.3.10 and 5.0.RC3. The only way around is is creating a custom AsyncClientHttpRequestFactory implementation that is based on the existing HttpComponentsAsyncClientHttpRequestFactory:
// package required for HttpComponentsAsyncClientHttpRequest visibility
package org.springframework.http.client;
import java.io.IOException;
import java.net.URI;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.Configurable;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.cache.CacheConfig;
import org.apache.http.impl.client.cache.CachingHttpAsyncClient;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.protocol.HttpContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
// TODO add support for other CachingHttpAsyncClient otpions, e.g. HttpCacheStorage
public class HttpComponentsCachingAsyncClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory implements AsyncClientHttpRequestFactory, InitializingBean {
private final CloseableHttpAsyncClient wrappedHttpAsyncClient;
private final CachingHttpAsyncClient cachingHttpAsyncClient;
public HttpComponentsCachingAsyncClientHttpRequestFactory() {
this(HttpAsyncClients.createDefault(), CacheConfig.DEFAULT);
}
public HttpComponentsCachingAsyncClientHttpRequestFactory(final CacheConfig config) {
this(HttpAsyncClients.createDefault(), config);
}
public HttpComponentsCachingAsyncClientHttpRequestFactory(final CloseableHttpAsyncClient client) {
this(client, CacheConfig.DEFAULT);
}
public HttpComponentsCachingAsyncClientHttpRequestFactory(final CloseableHttpAsyncClient client, final CacheConfig config) {
Assert.notNull(client, "HttpAsyncClient must not be null");
wrappedHttpAsyncClient = client;
cachingHttpAsyncClient = new CachingHttpAsyncClient(client, config);
}
#Override
public void afterPropertiesSet() {
startAsyncClient();
}
private void startAsyncClient() {
if (!wrappedHttpAsyncClient.isRunning()) {
wrappedHttpAsyncClient.start();
}
}
#Override
public ClientHttpRequest createRequest(final URI uri, final HttpMethod httpMethod) throws IOException {
throw new IllegalStateException("Synchronous execution not supported");
}
#Override
public AsyncClientHttpRequest createAsyncRequest(final URI uri, final HttpMethod httpMethod) throws IOException {
startAsyncClient();
final HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
HttpContext context = createHttpContext(httpMethod, uri);
if (context == null) {
context = HttpClientContext.create();
}
// Request configuration not set in the context
if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
// Use request configuration given by the user, when available
RequestConfig config = null;
if (httpRequest instanceof Configurable) {
config = ((Configurable) httpRequest).getConfig();
}
if (config == null) {
config = createRequestConfig(cachingHttpAsyncClient);
}
if (config != null) {
context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
}
}
return new HttpComponentsAsyncClientHttpRequest(cachingHttpAsyncClient, httpRequest, context);
}
#Override
public void destroy() throws Exception {
try {
super.destroy();
} finally {
wrappedHttpAsyncClient.close();
}
}
}

Create a Pool of JAXB Unmarshaller

I was looking around to find a way to improve JAXB Unmarshalling performances processing huge sets of files and found the following advice:
"If you really care about the performance, and/or your application is going to read a lot of small documents, then creating Unmarshaller could be relatively an expensive operation. In that case, consider pooling Unmarshaller objects"
Googling the web to find an example of this didn't return anything, so I thought it may be of interest to put my implementation here using Spring 3.0 and Apache Commons Pool.
UnmarshallerFactory.java
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.springframework.stereotype.Component;
/**
* Pool of JAXB Unmarshallers.
*
*/
#Component
public class UnmarshallerFactory implements KeyedPoolableObjectFactory {
// Map of JAXB Contexts
#SuppressWarnings("rawtypes")
private final static Map<Object, JAXBContext> JAXB_CONTEXT_MAP = new HashMap<Object, JAXBContext>();
#Override
public void activateObject(final Object arg0, final Object arg1) throws Exception {
}
#Override
public void passivateObject(final Object arg0, final Object arg1) throws Exception {
}
#Override
public final void destroyObject(final Object key, final Object object) throws Exception {
}
/**
* Create a new instance of Unmarshaller if none exists for the specified
* key.
*
* #param unmarshallerKey
* : Class used to create an instance of Unmarshaller
*/
#SuppressWarnings("rawtypes")
#Override
public final Object makeObject(final Object unmarshallerKey) {
if (unmarshallerKey instanceof Class) {
Class clazz = (Class) unmarshallerKey;
// Retrieve or create a JACBContext for this key
JAXBContext jc = JAXB_CONTEXT_MAP.get(unmarshallerKey);
if (jc == null) {
try {
jc = JAXBContext.newInstance(clazz);
// JAXB Context is threadsafe, it can be reused, so let's store it for later
JAXB_CONTEXT_MAP.put(unmarshallerKey, jc);
} catch (JAXBException e) {
// Deal with that error here
return null;
}
}
try {
return jc.createUnmarshaller();
} catch (JAXBException e) {
// Deal with that error here
}
}
return null;
}
#Override
public final boolean validateObject(final Object key, final Object object) {
return true;
}
}
UnmarshallerPool.java
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class UnmarshallerPool extends GenericKeyedObjectPool {
#Autowired
public UnmarshallerPool(final UnmarshallerFactory unmarshallerFactory) {
// Make usage of the factory created above
super(unmarshallerFactory);
// You'd better set the properties from a file here
this.setMaxIdle(4);
this.setMaxActive(5);
this.setMinEvictableIdleTimeMillis(30000);
this.setTestOnBorrow(false);
this.setMaxWait(1000);
}
public UnmarshallerPool(UnmarshallerFactory objFactory,
GenericKeyedObjectPool.Config config) {
super(objFactory, config);
}
#Override
public Object borrowObject(Object key) throws Exception {
return super.borrowObject(key);
}
#Override
public void returnObject(Object key, Object obj) throws Exception {
super.returnObject(key, obj);
}
}
And in your class that require a JAXB Unmarshaller:
// Autowiring of the Pool
#Resource(name = "unmarshallerPool")
private UnmarshallerPool unmarshallerPool;
public void myMethod() {
Unmarshaller u = null;
try {
// Borrow an Unmarshaller from the pool
u = (Unmarshaller) this.unmarshallerPool.borrowObject(MyJAXBClass.class);
MyJAXBClass myJAXBObject = (MyJAXBClass) u.unmarshal(url);
// Do whatever
} catch (Exception e) {
// Deal with that error
} finally {
try {
// Return the Unmarshaller to the pool
this.unmarshallerPool.returnObject(MyJAXBClass.class, u);
} catch (Exception ignore) {
}
}
}
This example is naive as it uses only one Class to create the JAXBContext and uses the same Class instance as the Key for the Keyed Pool. This can be improved by passing an Array of Classes as parameter rather than only one Class.
Hope this can help.
The creation of unmarshallers is intended to be light. I would recommend doing some profiling before developing a pooling strategy.

Access properties file programmatically with Spring?

We use the code below to inject Spring beans with properties from a properties file.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:/my.properties"/>
</bean>
<bean id="blah" class="abc">
<property name="path" value="${the.path}"/>
</bean>
Is there a way we can access the properties programmatically? I'm trying to do some code without dependency injection. So I'd like to just have some code like this:
PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer();
props.load("classpath:/my.properties");
props.get("path");
How about PropertiesLoaderUtils?
Resource resource = new ClassPathResource("/my.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
If all you want to do is access placeholder value from code, there is the #Value annotation:
#Value("${settings.some.property}")
String someValue;
To access placeholders From SPEL use this syntax:
#('${settings.some.property}')
To expose configuration to views that have SPEL turned off, one can use this trick:
package com.my.app;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.stereotype.Component;
#Component
public class PropertyPlaceholderExposer implements Map<String, String>, BeanFactoryAware {
ConfigurableBeanFactory beanFactory;
#Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
}
protected String resolveProperty(String name) {
String rv = beanFactory.resolveEmbeddedValue("${" + name + "}");
return rv;
}
#Override
public String get(Object key) {
return resolveProperty(key.toString());
}
#Override
public boolean containsKey(Object key) {
try {
resolveProperty(key.toString());
return true;
}
catch(Exception e) {
return false;
}
}
#Override public boolean isEmpty() { return false; }
#Override public Set<String> keySet() { throw new UnsupportedOperationException(); }
#Override public Set<java.util.Map.Entry<String, String>> entrySet() { throw new UnsupportedOperationException(); }
#Override public Collection<String> values() { throw new UnsupportedOperationException(); }
#Override public int size() { throw new UnsupportedOperationException(); }
#Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); }
#Override public void clear() { throw new UnsupportedOperationException(); }
#Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
#Override public String remove(Object key) { throw new UnsupportedOperationException(); }
#Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}
And then use the exposer to expose properties to a view:
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
<property name="attributesMap">
<map>
<entry key="config">
<bean class="com.my.app.PropertyPlaceholderExposer" />
</entry>
</map>
</property>
</bean>
Then in view, use the exposed properties like this:
${config['settings.some.property']}
This solution has the advantage that you can rely on standard placeholder
implementation injected by the context:property-placeholder tag.
Now as a final note, if you really need a to capture all placeholder properties and their values, you have to pipe them through StringValueResolver to make sure that placeholders work inside the property values as expected. The following code will do that.
package com.my.app;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.StringValueResolver;
public class AppConfig extends PropertyPlaceholderConfigurer implements Map<String, String> {
Map<String, String> props = new HashMap<String, String>();
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
this.props.clear();
for (Entry<Object, Object> e: props.entrySet())
this.props.put(e.getKey().toString(), e.getValue().toString());
super.processProperties(beanFactory, props);
}
#Override
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
StringValueResolver valueResolver) {
super.doProcessProperties(beanFactoryToProcess, valueResolver);
for(Entry<String, String> e: props.entrySet())
e.setValue(valueResolver.resolveStringValue(e.getValue()));
}
// Implement map interface to access stored properties
#Override public Set<String> keySet() { return props.keySet(); }
#Override public Set<java.util.Map.Entry<String, String>> entrySet() { return props.entrySet(); }
#Override public Collection<String> values() { return props.values(); }
#Override public int size() { return props.size(); }
#Override public boolean isEmpty() { return props.isEmpty(); }
#Override public boolean containsValue(Object value) { return props.containsValue(value); }
#Override public boolean containsKey(Object key) { return props.containsKey(key); }
#Override public String get(Object key) { return props.get(key); }
#Override public void clear() { throw new UnsupportedOperationException(); }
#Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
#Override public String remove(Object key) { throw new UnsupportedOperationException(); }
#Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}
I have done this and it has worked.
Properties props = PropertiesLoaderUtils.loadAllProperties("my.properties");
PropertyPlaceholderConfigurer props2 = new PropertyPlaceholderConfigurer();
props2.setProperties(props);
That should work.
CREDIT: Programmatic access to properties in Spring without re-reading the properties file
I've found a nice implementation of accessing the properties programmatically in spring without reloading the same properties that spring has already loaded. [Also, It is not required to hardcode the property file location in the source]
With these changes, the code looks cleaner & more maintainable.
The concept is pretty simple. Just extend the spring default property placeholder (PropertyPlaceholderConfigurer) and capture the properties it loads in the local variable
public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {
private static Map<String, String> propertiesMap;
// Default as in PropertyPlaceholderConfigurer
private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
#Override
public void setSystemPropertiesMode(int systemPropertiesMode) {
super.setSystemPropertiesMode(systemPropertiesMode);
springSystemPropertiesMode = systemPropertiesMode;
}
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
super.processProperties(beanFactory, props);
propertiesMap = new HashMap<String, String>();
for (Object key : props.keySet()) {
String keyStr = key.toString();
String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
propertiesMap.put(keyStr, valueStr);
}
}
public static String getProperty(String name) {
return propertiesMap.get(name).toString();
}
}
Usage Example
SpringPropertiesUtil.getProperty("myProperty")
Spring configuration changes
<bean id="placeholderConfigMM" class="SpringPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="locations">
<list>
<value>classpath:myproperties.properties</value>
</list>
</property>
</bean>
Hope this helps to solve the problems you have
You can also use either the spring utils, or load properties via the PropertiesFactoryBean.
<util:properties id="myProps" location="classpath:com/foo/myprops.properties"/>
or:
<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:com/foo/myprops.properties"/>
</bean>
Then you can pick them up in your application with:
#Resource(name = "myProps")
private Properties myProps;
and additionally use these properties in your config:
<context:property-placeholder properties-ref="myProps"/>
This is also in the docs: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-util-properties
Create a class like below
package com.tmghealth.common.util;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
#Component
#Configuration
#PropertySource(value = { "classpath:/spring/server-urls.properties" })
public class PropertiesReader extends PropertyPlaceholderConfigurer {
#Override
protected void processProperties(
ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
super.processProperties(beanFactory, props);
}
}
Then wherever you want to access a property use
#Autowired
private Environment environment;
and getters and setters then access using
environment.getProperty(envName
+ ".letter.fdi.letterdetails.restServiceUrl");
-- write getters and setters in the accessor class
public Environment getEnvironment() {
return environment;
}`enter code here`
public void setEnvironment(Environment environment) {
this.environment = environment;
}
You can get your properties through Environment class. As documentation stands:
Properties play an important role in almost all applications, and may originate from a variety of sources: properties files, JVM system properties, system environment variables, JNDI, servlet context parameters, ad-hoc Properties objects, Maps, and so on. The role of the environment object with relation to properties is to provide the user with a convenient service interface for configuring property sources and resolving properties from them.
Having Environment as a env variable, simply call:
env.resolvePlaceholders("${your-property:default-value}")
You can get your 'raw' properties through:
env.getProperty("your-property")
It will search through all properties source that spring has registered.
You can either obtain Environment through:
inject ApplicationContext by implementing ApplicationContextAware and then call getEnvironment() on context
implement EnvironmentAware.
It's obtain through implementation of a class because properties are resolved on early stage of application startup, as they may be required for bean construction.
Read more on documentation: spring Environment documentation
As you know the newer versions of Spring don't use the PropertyPlaceholderConfigurer and now use another nightmarish construct called PropertySourcesPlaceholderConfigurer. If you're trying to get resolved properties from code, and wish the Spring team gave us a way to do this a long time ago, then vote this post up! ... Because this is how you do it the new way:
Subclass PropertySourcesPlaceholderConfigurer:
public class SpringPropertyExposer extends PropertySourcesPlaceholderConfigurer {
private ConfigurableListableBeanFactory factory;
/**
* Save off the bean factory so we can use it later to resolve properties
*/
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
final ConfigurablePropertyResolver propertyResolver) throws BeansException {
super.processProperties(beanFactoryToProcess, propertyResolver);
if (beanFactoryToProcess.hasEmbeddedValueResolver()) {
logger.debug("Value resolver exists.");
factory = beanFactoryToProcess;
}
else {
logger.error("No existing embedded value resolver.");
}
}
public String getProperty(String name) {
Object propertyValue = factory.resolveEmbeddedValue(this.placeholderPrefix + name + this.placeholderSuffix);
return propertyValue.toString();
}
}
To use it, make sure to use your subclass in your #Configuration and save off a reference to it for later use.
#Configuration
#ComponentScan
public class PropertiesConfig {
public static SpringPropertyExposer commonEnvConfig;
#Bean(name="commonConfig")
public static PropertySourcesPlaceholderConfigurer commonConfig() throws IOException {
commonEnvConfig = new SpringPropertyExposer(); //This is a subclass of the return type.
PropertiesFactoryBean commonConfig = new PropertiesFactoryBean();
commonConfig.setLocation(new ClassPathResource("META-INF/spring/config.properties"));
try {
commonConfig.afterPropertiesSet();
}
catch (IOException e) {
e.printStackTrace();
throw e;
}
commonEnvConfig.setProperties(commonConfig.getObject());
return commonEnvConfig;
}
}
Usage:
Object value = PropertiesConfig.commonEnvConfig.getProperty("key.subkey");
This help me:
ApplicationContextUtils.getApplicationContext().getEnvironment()
Here is another sample .
XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);
This will resolve any nested properties.
public class Environment extends PropertyPlaceholderConfigurer {
/**
* Map that hold all the properties.
*/
private Map<String, String> propertiesMap;
/**
* Iterate through all the Property keys and build a Map, resolve all the nested values before building the map.
*/
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
super.processProperties(beanFactory, props);
propertiesMap = new HashMap<String, String>();
for (Object key : props.keySet()) {
String keyStr = key.toString();
String valueStr = beanFactory.resolveEmbeddedValue(placeholderPrefix + keyStr.trim() + DEFAULT_PLACEHOLDER_SUFFIX);
propertiesMap.put(keyStr, valueStr);
}
}
/**
* This method gets the String value for a given String key for the property files.
*
* #param name - Key for which the value needs to be retrieved.
* #return Value
*/
public String getProperty(String name) {
return propertiesMap.get(name).toString();
}
This post also explatis howto access properties: http://maciej-miklas.blogspot.de/2013/07/spring-31-programmatic-access-to.html
You can access properties loaded by spring property-placeholder over such spring bean:
#Named
public class PropertiesAccessor {
private final AbstractBeanFactory beanFactory;
private final Map<String,String> cache = new ConcurrentHashMap<>();
#Inject
protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public String getProperty(String key) {
if(cache.containsKey(key)){
return cache.get(key);
}
String foundProp = null;
try {
foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");
cache.put(key,foundProp);
} catch (IllegalArgumentException ex) {
// ok - property was not found
}
return foundProp;
}
}
This is the finest way I got it to work:
package your.package;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
public class ApplicationProperties {
private Properties properties;
public ApplicationProperties() {
// application.properties located at src/main/resource
Resource resource = new ClassPathResource("/application.properties");
try {
this.properties = PropertiesLoaderUtils.loadProperties(resource);
} catch (IOException ex) {
Logger.getLogger(ApplicationProperties.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getProperty(String propertyName) {
return this.properties.getProperty(propertyName);
}
}
create .properties file in classpath of your project and add path configuration in xml`<context:property-placeholder location="classpath*:/*.properties" />`
in servlet-context.xml after that u can directly use your file everywhere
Please use the below code in your spring configuration file to load the file from class path of your application
<context:property-placeholder
ignore-unresolvable="true" ignore-resource-not-found="false" location="classpath:property-file-name" />
I know this is an old thread, however, this topic in my opinion becomes of great importance for those using the functional approach for all those usecases where you need a microservice that loads "instantly" and therefore you avoid using annotations.
The problem that remained unsolved was to load eventually the environment variables which I had in my application.yml.
public class AppPropsLoader {
public static Properties load() {
var propPholderConfig = new PropertySourcesPlaceHolderConfigurer();
var yaml = new YamlPropertiesFactoryBean();
ClassPathResource resource = new ClassPathResource("application.yml");
Objects.requireNonNull(resource, "File application.yml does not exist");
yaml.setResources(resource);
Objects.requireNonNull(yaml.getObject(), "Configuration cannot be null");
propPholderConfig.postProcessBeanFactory(new DefaultListableBeanFactory());
propPholderConfig.setProperties(yaml.getObject());
PropertySources appliedPropertySources =
propPholderConfig.getAppliedPropertySources();
var resolver = new PropertySourcesPlaceholderResolver(appliedPropertySources);
Properties resolvedProps = new Properties();
for (Map.Entry<Object, Object> prop: yaml.getObject().entrySet()) {
resolvedProps.setProperty((String)prop.getKey(),
getPropertyValue(resolver.resolvePlaceHolders(prop.getValue()));
}
return resolvedProps;
}
static String getPropertyValue(Object prop) {
var val = String.valueOf(prop);
Pattern p = Pattern.compile("^(\\$\\{)([a-zA-Z0-9-._]+)(\\})$");
Matcher m = p.matcher(val);
if(m.matches()) {
return System.getEnv(m.group(2));
}
return val;
}
}

Resources