In a nutshell: cannot do remote lookup of a datasource in JNDI in versions superior to Jboss AS 7.
I’ll show you a basic example of how a customer can try to recover a datasource of the JNDI in versions superior to the Jboss AS 7, demonstrating some problems that occur and what makes it impossible to do this.
I’m considering that your AS is all set up, so I won’t be handling any of this, just the stages after the datasource.
Below is a common example of how we declare datasources in Wildfly:
<datasource jta="true" jndi-name="java:jboss/datasources/SOPT" pool-name="poolSOPT" enabled="true" use-ccm="true">
<connection-url>jdbc:postgresql://192.168.99.10:5432/stack</connection-url>
<driver>postgresql</driver>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>30</max-pool-size>
<use-strict-min>false</use-strict-min>
<flush-strategy>IdleConnections</flush-strategy>
</pool>
<security>
<user-name>postgres</user-name>
<password>postgres</password>
</security>
<validation>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
<background-validation>true</background-validation>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
</validation>
<timeout>
<blocking-timeout-millis>30000</blocking-timeout-millis>
<idle-timeout-minutes>5</idle-timeout-minutes>
</timeout>
<statement>
<prepared-statement-cache-size>1000</prepared-statement-cache-size>
<share-prepared-statements>true</share-prepared-statements>
</statement>
</datasource>
This will be our first trial (with the exception of jndi-name
, as mentioned below) and after starting AS is expected to be published, as log below:
INFO [o.j.a.c.s.datasources] (MSC service thread 1-13) JBAS010400: Bound data source [java:jboss/datasources/SOPT]
As our test is for remote recovery of the resource, we will rather make a change as noted below:
resources published in java:jboss/exported
are remotely accessible
That said, our jndi-name
will not be java:jboss/datasources/SOPT
, but yes java:jboss/exported/datasources/SOPT
, and remove the attribute jta
. Once this is done, with the server running, we will now create a client class to retrieve the datasource. I will configure the properties directly in the code, but you can create a file called jndi.properties
, by default the InitialContext
retrieves information from there.
I created a project Maven basic, containing only the dependencies really needed for the context:
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-remote-naming</artifactId>
<version>2.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-nio</artifactId>
<version>3.3.4.Final</version>
</dependency>
In your case only the jboss-client.jar
just, it brings everything that is needed to recover remote resources.
To make the lookup of the resource, we will use this code snippet:
final Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
properties.put(Context.SECURITY_CREDENTIALS, "${seu.usuario}");
properties.put(Context.SECURITY_CREDENTIALS, "${sua.senha}");
final Context context = new InitialContext(properties);
final DataSource ds = (DataSource) context.lookup("java:/datasources/SOPT");
Now we will execute for the datasource as above, below the log of the execution, where we get error:
fev 09, 2016 4:39:40 PM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.0.Final
fev 09, 2016 4:39:40 PM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.4.Final
fev 09, 2016 4:39:40 PM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 4.0.0.Final
fev 09, 2016 4:39:40 PM org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1$MessageReceiver handleMessage
ERROR: org.jboss.remoting3.MessageCancelledException
fev 09, 2016 4:39:40 PM org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1$MessageReceiver handleMessage
ERROR: org.jboss.remoting3.MessageCancelledException
Exception in thread "main" org.jboss.naming.remote.protocol.NamingIOException: Failed to lookup [Root exception is java.io.NotSerializableException: org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl]
at org.jboss.naming.remote.client.ClientUtil.namingException(ClientUtil.java:49)
at org.jboss.naming.remote.protocol.v1.Protocol$1.execute(Protocol.java:104)
at org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1.lookup(RemoteNamingStoreV1.java:95)
at org.jboss.naming.remote.client.HaRemoteNamingStore$1.operation(HaRemoteNamingStore.java:276)
at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:137)
at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
at org.jboss.naming.remote.client.RemoteContext.lookupInternal(RemoteContext.java:104)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:93)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:146)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.brunocesar.JNDIResource.main(JNDIResource.java:19)
Caused by: java.io.NotSerializableException: org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
at org.jboss.naming.remote.protocol.v1.Protocol$1$2.write(Protocol.java:138)
at org.jboss.naming.remote.protocol.v1.WriteUtil.write(WriteUtil.java:61)
at org.jboss.naming.remote.protocol.v1.Protocol$1.handleServerMessage(Protocol.java:128)
at org.jboss.naming.remote.protocol.v1.RemoteNamingServerV1$MessageReciever$1.run(RemoteNamingServerV1.java:73)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: an exception which occurred:
in field cachedConnectionManager
in field cm
in object org.jboss.jca.adapters.jdbc.WrapperDataSource@2e275207
This is due to the cache settings in our datasource, as the attribute use-ccm
, etc.., CachedConnectionManagerImpl
, attribute of wrapper that Wildfly uses, is not serializable, so a NotSerializableException
is launched. Let’s try without the attribute use-ccm
and also without the other configurations that somehow have relationship with the pool of connections, then our new datasource will look like this, only the essential:
<datasource jndi-name="java:jboss/exported/datasources/SOPT" pool-name="poolSOPT" enabled="true">
<connection-url>jdbc:postgresql://192.168.99.10:5432/stack</connection-url>
<driver>postgresql</driver>
<security>
<user-name>postgres</user-name>
<password>postgres</password>
</security>
</datasource>
After re-testing the error will persist:
fev 09, 2016 4:40:27 PM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.0.Final
fev 09, 2016 4:40:27 PM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.4.Final
fev 09, 2016 4:40:27 PM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 4.0.0.Final
fev 09, 2016 4:40:28 PM org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1$MessageReceiver handleMessage
ERROR: org.jboss.remoting3.MessageCancelledException
fev 09, 2016 4:40:28 PM org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1$MessageReceiver handleMessage
ERROR: org.jboss.remoting3.MessageCancelledException
Exception in thread "main" org.jboss.naming.remote.protocol.NamingIOException: Failed to lookup [Root exception is java.io.NotSerializableException: org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl]
at org.jboss.naming.remote.client.ClientUtil.namingException(ClientUtil.java:49)
at org.jboss.naming.remote.protocol.v1.Protocol$1.execute(Protocol.java:104)
at org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1.lookup(RemoteNamingStoreV1.java:95)
at org.jboss.naming.remote.client.HaRemoteNamingStore$1.operation(HaRemoteNamingStore.java:276)
at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:137)
at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
at org.jboss.naming.remote.client.RemoteContext.lookupInternal(RemoteContext.java:104)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:93)
at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:146)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.brunocesar.JNDIResource.main(JNDIResource.java:19)
Caused by: java.io.NotSerializableException: org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
at org.jboss.naming.remote.protocol.v1.Protocol$1$2.write(Protocol.java:138)
at org.jboss.naming.remote.protocol.v1.WriteUtil.write(WriteUtil.java:61)
at org.jboss.naming.remote.protocol.v1.Protocol$1.handleServerMessage(Protocol.java:128)
at org.jboss.naming.remote.protocol.v1.RemoteNamingServerV1$MessageReciever$1.run(RemoteNamingServerV1.java:73)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: an exception which occurred:
in field cachedConnectionManager
in field cm
in object org.jboss.jca.adapters.jdbc.WrapperDataSource@686ac2e7
There’s nothing else in this datasource that we can withdraw, pool-name
is obligatory, then we just find that even summing up the datasource at most there are still objects in it that are not serializable, basic premise so that it can be recovered remotely.
That is, the resource is even published, we can validate with this code:
final Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
properties.put(Context.SECURITY_CREDENTIALS, "${seu.usuario}");
properties.put(Context.SECURITY_CREDENTIALS, "${sua.senha}");
final Context context = new InitialContext(properties);
final NamingEnumeration<NameClassPair> namings = context.list("java:/datasources");
if (namings.hasMoreElements()) {
final NameClassPair name = namings.next();
System.out.println(name.getName() + " | " + name.getClassName());
}
That I printed out SOPT | org.jboss.jca.adapters.jdbc.WrapperDataSource
, but because some objects are not serializable there is no way to do the lookup successfully.
I don’t know what your context is, which forces you to remotely retrieve a datasource from AS. If you want to use remote things like this (is it a prerequisite?), consider evolving your architecture, such as using services, remote Ejbs, etc.
Testing was done on version 8.1.0 of Wildfly, which was the one you originally posted. You can repeat the procedure and see if in version 10.0.0 the behavior is still the same.
Some other links talking about this:
The error persisted even though changing it
– Ingo Guilherme Both Eyng
I did a search, it seems that it is something related to me being using external client. The
InitialContext
without the properties returns me to Exceptionjavax.naming.NoInitialContextException
. The server log tells me nothing but[org.jboss.as.naming] (default task-19) JBAS011806: Channel end notification received, closing channel Channel ID 21b908c3 (inbound) of Remoting connection 7be8f674 to /127.0.0.1:54170
– Ingo Guilherme Both Eyng
Server log: http://paste.ubuntu.com/15002418/. Eclipse log: http://paste.ubuntu.com/15002423/. I am trying to connect via code in a parallel project, I am not using Works4bimes1-Webservice and Works4bimes1-Interfaceweb yet. This eclipse parallel project contains only one connection class for the test that is the code above and one main to invoke the method. Project: http://i.imgur.com/Fy2okow.jpg.
– Ingo Guilherme Both Eyng