Get Datasources programmatically - java

I have a web-app in Java/Java EE deployed on any application server/web server. I would like to get all the datasources configured on this server in my application.
Does anyone have any ideas to achieve it? I can get those through WLST ant tasks. But I need to get them programatically.

If your datasources are configured with JNDI then you can list the context and can get all the names (more from here) with Context.list() method and from those name you can find all the datasources
the Context.list() returns an enumeration of NameClassPair. Each NameClassPair consists of the object's name and its class name. So just iterate it and check the class name for java.sql.DataSource and then get the object name to retrieve it.

With JBoss you can do the following (assuming JMX is available):
Context ctx = new InitialContext();
MBeanServerConnection mconn = (MBeanServerConnection)ctx.lookup("jmx/invoker/RMIAdaptor");
ObjectName name = new ObjectName("jboss.jca:service=DataSourceBinding,*");
Set s = mconn.queryMBeans(name, null);
Where s is an mbeans collection.

Related

How do I lookup DomainRuntimeServiceMBean from JNDI from a Local Connection?

I have searched the Weblogic documentation extensively:
All the documentation on the Oracle site and all the examples I have found so far only show how to get a reference to this MBean via a Remote connection or to an instance of MBeanServer locally.
The little bit that mentions a local connection is vague and incomplete:
Absolute JNDI name of the MBean server. The JNDI name must start with
/jndi/ and be followed by one of the JNDI names described in Table
4-1.
Table 4-1 shows:
MBean Server JNDI Name
Domain Runtime MBean Server weblogic.management.mbeanservers.domainruntime
This doesn't work, I tried dumping the JNDI tree and can't find anything relevant in there.
I am on the AdminServer so that isn't the issue.
What I can find instructions to do that works is getting a reference to an instance of MBServer, but that isn't what I need; example: (MBeanServer) ctx.lookup("java:comp/env/jmx/domainRuntime");
But this doesn't do me any good, it is an instance of MBeanServer and I don't want to dig through all the indirection with the ObjectName stuff.
What I need to reference is DomainRuntimeServiceMBean interface:
What I need is to be able to get an instance of DomainRuntimeServiceMBean - JavaDoc
Short Answer
The type safe interfaces are all Deprecated, you have to do the lookup/tree walking manually.
As of 9.0, the MBeanHome interface and all type-safe interfaces for
WebLogic Server MBeans are deprecated. Instead, JMX applications that
interact with WebLogic Server MBeans should use standard JMX design
patterns in which clients use the
javax.management.MBeanServerConnection interface to discover MBeans,
attributes, and attribute types at runtime.
Long Answer
private InitialContext ctx;
private MBeanServer domain;
private ObjectName domainObjectName;
In the constructor:
ctx = new InitialContext();
this.domain = (MBeanServer) ctx.lookup("java:comp/env/jmx/domainRuntime");
this.domainObjectName = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
In your method:
final ObjectName dr = (ObjectName) this.domain.getAttribute(domainObjectName, "DomainRuntime");
final ObjectName dm = (ObjectName) this.domain.getAttribute(dr, "DeploymentManager");
final ObjectName[] adrs = (ObjectName[]) this.domain.getAttribute(dm, "AppDeploymentRuntimes");
for (final ObjectName on : adrs)
{
if (this.domain.getAttribute(on, "ApplicationName").equals(appName))
{
this.domain.invoke(on, "stop", null, null);
break;
}
}
Of course now I have to write my own convenience classes that are typesafe to wrap all this verbose non-sense!

How to connect to WebSphere in J2EE client environment?

I'm trying to connect to EJB on WebSphere 7.0. The EJB requires javax.ejb.SessionContext and reads Principal from it, so I need to log in before calling it.
I'm using the following code in stand-alone application:
import javax.naming.InitialContext;
import javax.security.auth.login.LoginContext;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
public static void main(String[] args) throws Exception {
InitialContext ic = new InitialContext(System.getProperties());
LoginContext lc = new LoginContext("WSLogin",
new WSCallbackHandlerImpl("myuser","mypass"));
lc.login();
WSSubject.setRunAsSubject(lc.getSubject());
SessionContext sessionContext=(SessionContext) ic.lookup(
"java:comp/env/sessionContext");
}
I've added the entry to my jmxremote.access:
myuser readwrite
However, I get an exception:
Caused by: javax.naming.ConfigurationException: Name space accessor
for the java: name space has not been set. Possible cause is that the
user is specifying a java: URL name in a JNDI Context method call but
is not running in a J2EE client or server environment. at
com.ibm.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:98)
at
com.ibm.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:82)
at
javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at
javax.naming.spi.NamingManager.getURLContext(NamingManager.java:533)
at
javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:320)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
What else should I do, to run my code in the 'J2EE client environment' mentionend in the error message?
In order to use java:comp, you would need to package the client application in an .ear and use launchClient. Ultimately, that's just going to use -CCBootstrapHost/-CCBootstrapPort (or defaults) to connect to the target server to look up the EJB, so you could just use the EJB thinclient and use the fully-qualified EJB binding name instead (see the CNTR0167I messages in SystemOut.log).
you'll need to use the WAS client runtime JARs. WAS_HOME/AppServer/runtimes. You will need the ORB and the other service specific JARs. As an alternative to using launchClient, you can manually specify the context factory you'll be using here:
InitialContext ic = new InitialContext(System.getProperties());
set the
java.naming.factory.initial
variable (in your system env or in a Properties object) to
com.ibm.websphere.naming.WsnInitialContextFactory`

JNDI lookup - Is it a correct way in my app?

I am writing an application in Java and I have some REST web services there. My application has following structure: http://cl.ly/L7Pv/o
REST web service classes are Stateless session beans. It works like charm. But Classes in red on the picture want to use that REST resources too.
As fas as I know I cannot use dependency injection and annotation #EJB there. I believe I have to use JNDI lookup. Documentation: http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html
But now I dont know how to write this JNDI lookup. I have tried these two:
context.lookup("java:global/diplomka/ListResource");
context.lookup("java:global/Diplomka_maven/ListResource");
What am I doing wrong? Is this a correct approach in the first place?
Thank you
If these classes (ListResource etc.) are Stateless session beans, you can put attribute name or mappedName in #Stateless annotation, e.g.:
#Stateless(mappedName="ejb/myRestService")
public class ListResource { ..
Once you have specified JNDI name of your stateless bean, it's easy to fetch the bean through JNDI lookup:
InitialContext ic = new InitialContext();
ListResource lr = (ListResource) ic.lookup("ejb/myRestService");
lr.doWhateverNeeded(..);

Configure JNDI names with Open EJB

I'm trying to (unit) test my EJB class without having to startup my websphere environment. Now I'm using Open EJB, but there are some issues with resolving the JNDI Names for other EJBs that are used within my EJB... and there is no way for me to inject mocked classes from my test right now.
Getting the InitialContext
final Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
properties.setProperty("log4j.category.OpenEJB.options ", "debug");
properties.setProperty("log4j.category.OpenEJB.startup ", "debug");
properties.setProperty("log4j.category.OpenEJB.startup.config ", "debug");
properties.setProperty("MyOwnDatasource.JdbcDriver ", "com.ibm.as400.access.AS400JDBCDriver");
properties.setProperty("MyOwnDataSource.JdbcUrl ", "jdbc:as400:MYHOSTNAME;database name=MYDATABASE;libraries=MYDEFAULTTABLE");
ic = new InitialContext(properties);
Inside my class under test there is a lookup for java:comp/env/ejb/PrefixEjbNameLocalHome and I can not set Open EJB to generate JNDI names in that format.
Additional Property for JNDI name format
I tried setting the formatting rule like this:
properties.setProperty("openejb.jndiname.format ", "comp/env/ejb/{interfaceClass}");
Properties aren't used?
Also the logging configuration isn't used. I'm only seeing INFO and WARN messages from Open EJB, although I set log4j.category.OpenEJB.* and the like to DEBUG or TRACE.
It's the "java:" part that is messing up your test case. Basically Context.INITIAL_CONTEXT_FACTORY and "java:" are mutually exclusive. The InitialContext class has a special understanding of "java:" or any "foo:" lookups and if they are at the beginning of the name it will not use INITIAL_CONTEXT_FACTORY you specified. A somewhat frustrating part of JNDI.
If you lookup the name exactly as printed in the log, it will work. So for example this log message:
INFO - Jndi(name=WidgetBeanRemote) --> Ejb(deployment-id=WidgetBean)
Then in code:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
// set any other properties you want
Context context = new InitialContext(p);
Object o = context.lookup("WidgetBeanRemote");

Object reference lookup from JNDI results in ClassCastException

I'm having problems calling EJB3 stateless bean outside the container.
Code for getting the object reference:
Context envCtx = (Context) context.lookup("ejb");
MyObject o = (MyObject) envCtx.lookup(MyObject);
The second row results in exception:
java.lang.ClassCastException: javax.naming.Reference
I use JBoss.org 5.1.0 GA.
Based on some other posts I suspect this might be due to wrong version of client libraries. However, I'm unsure which library jar(s) I should include in the jar? (I get the error using 5.0.4.GA jnpserver.)
For JBoss, your code should look something like that:
Properties properties = new Properties();
properties.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs","=org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url","localhost:1099");
Context context = new InitialContext(properties);
(EchoBeanRemote) c.lookup("EchoBean/remote");
If you prefer, you can put the JNDI environement settings in a jndi.properties file (that needs to be on the classpath):
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
And use the non-arg InitialContext constructor:
Context context = new InitialContext();
(EchoBeanRemote) c.lookup("EchoBean/remote");
This is obviously more portable.
And in both case, you'll need jbossall-client.jar on the classpath on the client side.
P.S.: You can check the Global JNDI Name your bean is registered at in the JNDI View of the web-based JMX console (if it still exists).

Categories

Resources