I saw a stackoverflow answer to a question on JNDI.
The answer showed a few lines of code using InitialContext to retrieve a DataSource.
However, the instance of InitialContext was not created with any properties to use any sort of service such as LDAP or the file system.
Where does the entry go when you bind it to an InitialContext with the null constructor ?
Will the entry only visible within the application ?
Will it not persist when you shutdown the application ?
Where does the entry go when you bind it to an InitialContext with the null constructor?
If there is a resource file named /jndi.properties it uses whatever environment is defined in there. Servlet containers typically use this to define an extra object factory for the java: namespace.
Will the entry only [be] visible within the application?
Yes.
Will it not persist when you shutdown the application?
It will not persist unless the container implements that.
Related
I'm trying to run a remote lookup to another Glassfish from a Servlet. So, I was following the link documentation (http://docs.oracle.com/cd/E19798-01/821-1752/beanv/index.html). First I created a Sateless Session Ben called CalculatorBean, packaged in an EJB JAR of the same name (CalculatorBean), the JNDI name was java:global/CalculatorBean/CalculatorBean.
According to the documentation, I created a Web project and declared my EJB in sub-web.xml the following file:
<ejb-ref>
<ejb-ref-name>ejb/CalculatorBean</ejb-ref-name>
<jndi-name>corbaname:iiop:127.0.0.1:3700#CalculatorBean/CalculatorBean</jndi-name>
</ejb-ref>
where 127.0.0.1 is the host of the machine (local!), 3700 is the default port for querying and, CalculatorBean/CalculatorBean is the global JNDI name. First question, theoretically the JNDI name passes into an interoperable String "CalculatorBean/CalculatorBean" instead of "java: global/CalculatorBean/CalculatorBean", right?
After that, I created a Servlet and put the following code snippet:
ctx = new InitialContext ();
bean = (CalculatorRemote) ctx.lookup ("java:comp/env/ejb/CalculatorBean");
Where, CalculatorRemote is the name of the remote interface that we included in the java project:comp/env/ is the directory section to access Java EE components and ejb/CalculatorBean is the name of my bean in the configuration of the sun-web.xml file
When put to run my Servlet I'm getting the exception:
Caused by: javax.naming.NameNotFoundException: No object bound to name java:comp/env/ejb/CalculatorBean
Obviously, it's not finding the name, however, do not really know what name I should use to set the lookup.
I had the same problem, and I solved it.
By default, your EJB is not visilbe into java:comp/env/ and you can not lookup for an EJB into InitialContext instance. But, you can successful lookup for an EJB after when at least one EJB instance is injected using #EJB annotation, like, for your example:
#EJB(name = "ejb/CalculatorBean")
private CalculatorRemote calc;
After that, CalculatorRemote EJB is visible in InitialContext instance.
I have two Spring applications, applA and applB, running in Tomcat - both use jarX.jar and applicationContext-x.xml.
So there's going to be one instance of a certain bean, defined in the above context, for each application.
I'm exposing the bean and some of its methods via JMX by using annotations.
now i want to write a test client which calls method of the bean, but sometimes i want to call the methods of the bean in applA and sometimes of the bean in applB.
How do i do that?
i also have a bean called jmxServerConfiguration in each application, each using a different port though.
currently in my JMX client i'm getting the bean by using
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(applicationContextName);
theBean = beanFactory.getBean(BEAN_NAME);
but i always get the bean of applA. how do i tell it whether i want the bean of applB or applA?
Should i perhaps, (how?), use
MBeanServerConnection connection = JmxUtils.getMBeanServerConnection(url);
and specify a different port in the url, depending on the appl from which i want to get the bean?
Set the default-domain on the MBean exporter to a different value for each application and use the appropriate ObjectName to access the bean(s) over JMX.
What is the best approach for creating services that load a property set at runtime (bean is passed "xyz" and loads xyz.properties)? These properties files need to be able to be dropped into a folder outside the classpath before a command is entered to start the service (edit: this could happen at any time while the program is running).
I already have a system to do this that we've been using for over a year, but I'm migrating to spring to make the code more modular (customize services more easily through DI) and easier to maintain. My current method of creating an environment and then passing it with "this" to the dependencies just seems upside down from an IoC standpoint.
Is there a way to use a PropertyPlaceholderConfigurer without hardcoding the name of the property file? Maybe just a reference to a variable I pass into the constructor of the service that its dependencies can load? So far, it looks like I will have to create a service and inject its dependencies without any config and then call a separate load method for each to pass in the properties, but that just seems like I'm not really using spring.
USE CASE: The app will pool client connections to various servers and will forward requests from other applications to these servers. New profiles must be able to be added by non-programmers without taking down or restarting the app. The profiles will include basic things like host, port, and login info, but also more complex things like whether to use tcp/http, ssl/https (which will determine which client type to use), and timeouts and pool min/max/etc (which will need default values).
I tried with PropertyPlaceholderConfigurer and frankly, I couldn't wrap my head around it, somehow. It's easy enough to use when you use the existing options but I couldn't extend the framework.
So my approach was much more simple:
Create an annotation #InjectConfig which takes a config key as parameter.
In your beans/services, annotate fields or public setters with this annotation.
Write a BeanPostProcessor which takes options from a "config provider" and injects them into the fields / setters.
Now all you need is a config provider. Inject that into the post processor and you're done.
Note: I prefer annotating setters because that means you can easily configure your services from tests (just call the setters) without having to come up with smart names for 238576 config files.
EDIT If you have many configs, then a config factory might be a better choice:
Create a key to describe a config bundle (I usually use an enum or a new type here to prevent typos)
Put this key into the service when you create it (manually or via Spring)
Write a config factory that can return Properties or a Map for a config key.
Inject this factory into your service
In the init code of your service, use the key to lookup your config via the factory.
Using this approach, you can have a dummy factory that always returns the same thing in tests and a more complex factory for production.
The real factory can then be configured via spring so it knows where to look for configuration files. One approach is to register a java.io.File per config key. Now your concerns (configuring a service and loading configs) are completely separated.
PropertyPlaceholderConfigurer reads and initialize files on application context initialization and only once. So most probably you cannot configure it at runtime.
But you can have variables. For example, for my case I have default properties and user specific properties. So PropertyPlaceholderConfigurer loads properties from classpath first and after that is trying to find additional properties at defined location (user home folder). I user's property file exists so configurer loads it and override properties.
Here is my example:
<bean id="config" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/> <!-- do not throw exception if file not found -->
<property name="locations">
<list>
<value>classpath:server.properties</value>
<value>file:${user.home}/user.properties</value>
</list>
</property>
</bean>
I'm not sure that this answer is what you're exactly need. But I'm trying to guess what is your actual task. So if you need re-read properties runtime each time you access them you have to do it manually like you did before because spring application context helps you configure your application initial configuration.
It seems like the best approach may be to use a ServiceManager that contains the main ApplicationContext and then have each Service initialize its own FileSystemXmlApplicationContext with the main context as the parent like so:
public class ServiceManager {
ApplicationContext appContext;
String APP_HOME = System.getProperty("user.home") + File.separator;
public void init() {
//set main spring context
appContext = new AnnotationConfigApplicationContext(AppConfig.class);
}
public void start(String serviceName) throws Exception {
ApplicationContext serviceContext = new FileSystemXmlApplicationContext(
new String[]{APP_HOME + serviceName + ".xml"}, //path to child ctx
appContext); //reference to parent ctx to build hierarchy
Service service = (Service) serviceContext.getBean("service");
service.start();
}
}
The ApplicationContext is a bit heavy to be duplicating, but memory is pretty cheap these days and this provides total separation of concerns. I still have shared logging and an event system managed by the parent context, and each service is now simplified in its own config. I built a proof of concept using two services, and it seems to work fine so far. I'll add another comment once I finish the other services and finish testing.
reference:
http://techo-ecco.com/blog/spring-application-context-hierarchy-and-contextsingletonbeanfactorylocator/
I have a web application trying to access a JNDI declared in WebSphere Application Server.
The JNDI is declared under Object pool managers. However, I'm receiving an error when I access the pool. The error says that comp/env/pool is not found in context "java:".
My code is written as follows:
InitialContext initialContext = new InitialContext();
ObjectPoolManager opm = (ObjectPoolManager)initialContext.lookup("java:comp/env/pool");
Accessing the pool via the code below works:
ObjectPoolManager opm = (ObjectPoolManager)initialContext.lookup("pool");
I'm confused because according to what I've found on the internet, java:comp/env/ is a default prefix for JNDI. So why does it cause an error in my case?
Thank you!
you can only use java:comp/env if you have declared a reference to the Object Pool in your web.xml under the resource-ref section.
See What is resource-ref in web.xml used for? for further explanation.
This question already has answers here:
What does java:comp/env/ do?
(3 answers)
Closed 2 years ago.
what is meant by java:comp/env ?
What does the look up like :
Context envContext = (Context)initContext.lookup("java:comp/env");
do ?
I understand that a look-up like :
(DataSource)envContext.lookup("jdbc/MyDatasource")
looks up for the name MyDatasource in the context.xml or web.xml to get the URL of the database. Is it so ? !! But what does the former look up do ?
java:comp/env is the node in the JNDI tree where you can find properties for the current Java EE component (a webapp, or an EJB).
Context envContext = (Context)initContext.lookup("java:comp/env");
allows defining a variable pointing directly to this node. It allows doing
SomeBean s = (SomeBean) envContext.lookup("ejb/someBean");
DataSource ds = (DataSource) envContext.lookup("jdbc/dataSource");
rather than
SomeBean s = (SomeBean) initContext.lookup("java:comp/env/ejb/someBean");
DataSource ds = (DataSource) initContext.lookup("java:comp/env/jdbc/dataSource");
Relative paths instead of absolute paths. That's what it's used for.
It's an in-memory global hashtable where you can store global variables by name.
The "java:" url scheme causes JNDI to look for a javaURLContextFactory class, which is usually provided by your app container, e.g. here is Tomcat's implementation javadoc
See also NamingManager.getURLContext
I know I'm far late, but I was asking the same question, and I think I came some answer. So, if I may put my two cents.
java:comp/env/jdbc/myDataSource
java: is just like jdbc: from connection string. Acts as a protocol.
comp is the root for all JNDI contexts.
env is the subcontext for all resource related. There is another for user. Check this out.
jdbc is the subcontext for jdbc resources. There are types. Check the link from the previous bullet.
myDataSource is the name of your jdbc resource.