Wildfly 12 infinispan cache lookup is not working - wildfly

I'm migration from wildfly 10 to wildfly 12. I have created local cache same as configured in wildfly 10.
standalone-full.xml configuration:
<cache-container name="DataCache" default-cache="modelcache" statistics-enabled="false">
<local-cache name="modelcache" statistics-enabled="false"/>
</cache-container>
Lookup code in singleton ejb annotated with #startup:
#Resource(lookup = "java:jboss/infinispan/container/DataCache")
private CacheContainer Container;
#PostConstruct
public void init() {
Container.start();
modelCache = Container.getCache("modelcache");
}
I'm getting the below exception while deploying file
Caused by:
org.infinispan.commons.CacheConfigurationException: ISPN000436: Cache 'modelcache' has been requested, but no cache configuration exists
with that name and no default cache has been set for this container
How to fix this?

Put
<resource-ref>
<res-ref-name>infinispan/DataCache</res-ref-name>
<lookup-name>java:jboss/infinispan/cache/DataCache/modelcache</lookup-name>
</resource-ref>
in jboss-web.xml. When requesting the cache do it like this (note that the name annotation property is used to specify the resource):
#Resource(name = "infinispan/DataCache")
private Cache<K, V> cache;
See this thread for more details: https://developer.jboss.org/thread/277425

Put the following entry in your project descriptor file (web.xml, ejb-jar.xml, etc)
<resource-ref>
<res-ref-name>infinispan/DataCache</res-ref-name>
<lookup-name>java:jboss/infinispan/container/DataCache</lookup-name>
</resource-ref>

For wildfly 10 you can lookup your infinispan cache or cache container in the following way
You need to define your cache in standalone-ha.xml(High availability) under the following subsystem
<cache-container name="myCacheContainer" default-cache="myCache" module="org.wildfly.clustering.ejb.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="myCache">
<expiration lifespan="86400000" max-idle="3600000"/>
</replicated-cache>
</cache-container>
Once you have defined the cache you can lookup either the cache or the container.
2.a To lookup the cache you should setup a resource ref element in your project
descriptor file i.e (web.xml,jboss-web.xml etc.)
infinispan/myCache
java:jboss/infinispan/cache/myCacheContainer/myCache
2.b If you want to lookup cache container instead you also need to define configuration lookup in your project descriptor. So resource ref looks like this
<resource-ref>
infinispan/myCacheContainer
org.infinispan.manager.CacheContainer
java:jboss/infinispan/container/myCacheContainer
infinispan/myCache-config
org.infinispan.configuration.cache.Configuration
java:jboss/infinispan/configuration/myCacheContainer/default
Now if using spring you can do a JNDI lookup for cache like this
<jee:jndi-lookup id="myCache"
jndi-name="infinispan/myCache" />
3.a Or you can lookup the container like this
<jee:jndi-lookup id="myCacheContainer"
jndi-name="infinispan/myCacheContainer" />
Now you can inject the cache like the following
#Resource(name="myCache")
private Cache cache;
4.a You can inject the container like the following
#Resource(name="myCacheContainer")
private CacheContainer cacheContainer;

Related

Infinispan Cache store - "class not found" Exception in wildlfy addon module

I am using the 11.0.7 Infinispan cache store which is configured with an XML file. I have imported that cache module in a Wildlfy server. I am using this dependency in my application. But when I try to fetch cache elements from cache, it gives me the exception ClassNotFound.
I have used this configuration:
<local-cache name="TaskStoreCache" statistics="false">
<locking acquire-timeout="60000" />
<persistence passivation="false">
<rocksdb-store path=" C:\CacheStore\Data\TaskStoreCache" preload="false" shared="false"
purge="false" read-only="false">
<expiration path="C: \CacheStore\Expired\TaskStoreCache"/>
</rocksdb-store>
</persistence>
<memory max-count="500"/>
<encoding media-type="application/x-java-object"/>
</local-cache>
And I used this serialization:
<serialization marshaller="org.infinispan.commons.marshall.JavaSerializationMarshaller">
<white-list>
<regex>com.xyz.cache.*</regex>
<regex>java.util.*</regex>
<regex>java.lang.*</regex>
</white-list>
</serialization>
I am sure it is a class loading related issue. Please help me with that.
You should double-check how the dependency is wrapped into your application (war/ear), and make sure the scope is correct.
If you did not pack it within your application, the module has to be present on your wildfly and known to your application (e.g. jboss-deployment-structure.xml)

Wildfly 10.1.0 getting "anonymous" as principal name in EJB

Problem Statement: context.getCallerPrincipal().getName() always gives "anonymous" with following client and server settings
I have done all the settings required. My security domain is using a Custom spring security module for JAAS login. The client acts as an installer for the application. The main application is deployed on wildfly 10.1 and installer launches as a standalone application which access the remote EJBs from the server. The EJB access is successfully but when I access caller principle from context it always gives "anonymous"
Client Side Settings:
jboss-ejb-client.properties:
remote.connections=default
remote.connection.default.port=8080
remote.connection.default.host=127.0.0.1
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=root
remote.connection.default.password=catch22*
Initial Context Creation:
Properties prop1 = new Properties();
prop1.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop1.put("org.jboss.ejb.client.scoped.context", "true");
System.out.println("setup() ################### 1");
context = new InitialContext(prop1);
Used jboss-client.jar
I have used the jboss-client.jar lib provided with in "WILDFLY_HOME/bin/client" directory
Server Side Settings
ejb realm:
Added following ejb realm in standalone-full.xml
<security-realm name="ejb-outbound-realm">
<server-identities>
<secret value="Q29ubmVjdGlvblBhc3N3b3JkMSE="/>
</server-identities>
</security-realm>
remoting subsystem settings:added out bound connection as follows
<outbound-connections>
<remote-outbound-connection name="ejb-outbound-connection" outbound-socket-binding-ref="ejb-outbound" security-realm="ejb-outbound-realm" username="root">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
Against out bound connection I have added following socket binding group
<outbound-socket-binding name="ejb-outbound">
<remote-destination host="localhost" port="8080"/>
</outbound-socket-binding>
application-users.properties:
root=7c5b7db204cb436044a4148094ef152e
application-roles.properties:
No change in this file
Session Bean Changes
#Stateless
#Local(AbstractEnterpriseSessionFacadeLocal.class)
#Remote(AbstractEnterpriseSessionFacadeRemote.class)
#SuppressWarnings({WarningConst.UNCHECKED, "rawtypes"})
#PermitAll
//#org.jboss.ejb3.annotation.SecurityDomain("acegi-simple")
public class AbstractEnterpriseSessionFacadeBean<T, E extends IGeneralObject> implements AbstractEnterpriseSessionFacade {
injection of context in above class
#Resource
private transient SessionContext context;
After above settings, when I am calling context.getCallerPrincipal().getName() it always gives me "anonymous"
Please help!

Wildfly 10 Infinispan TreeCache is not working

I'm migrating from Wildfly 8.2 to 10.1 Unfortunately, I'm encountering problems with Infinispan TreeCache.
Here are several issues:
Invocation batching is no longer supported in Wildfly 10
configuration
Here's my config:
<subsystem xmlns="urn:jboss:domain:infinispan:4.0">
...
<cache-container name="my_container" default-cache="my_tree_cache" jndi-name="java:jboss/my_container">
<transport lock-timeout="60000"/>
<local-cache name="my_cache"/>
<local-cache name="my_tree_cache" batching="true"/>
</cache-container>
</subsystem>
Error on startup:
> Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[345,17]
> Message: WFLYCTL0197: Unexpected attribute 'batching' encountered
If I remove "batching" attribute. I get this error:
com.daiwacm.modjsf.dataaccess.DataException: getTreeCache has failed for jndi value (my_tree_cache)
Caused by: org.infinispan.commons.CacheConfigurationException: invocationBatching is not
enabled for cache 'my_tree_cache'. Make sure this is enabled by calling configurationBuilder.invocationBatching().enable()
If I set batching programmatically:
Context context = new InitialContext();
CacheContainer cacheContainer = (CacheContainer) context.lookup(jndiName);
TreeCacheFactory tcf = new TreeCacheFactory();
Cache cache = cacheContainer.getCache(cacheName);
cache.getCacheManager().defineConfiguration(cacheName,
new ConfigurationBuilder().read(cache.getCacheConfiguration()).invocationBatching().enable().build());
TreeCache treeCache = tcf.createTreeCache(cache);
I get this error:
> Caused by: org.infinispan.commons.CacheConfigurationException:
> ISPN000381: This configuration is not supported for simple cache
> at org.infinispan.configuration.cache.ConfigurationBuilder.validateSimpleCacheConfiguration(ConfigurationBuilder.java:219)
> ...
> at org.infinispan.configuration.cache.InvocationBatchingConfigurationBuilder.build(InvocationBatchingConfigurationBuilder.java:12)
> ...
Don't set the configuration programmatically; I am not sure this is a valid approach, despite it seems to ~work.
The configuration option you're looking for is
<local-cache name="my_cache">
<transaction transaction-mode="BATCH" />
</local-cache>
(please consult the schema in docs/schema/jboss-as-infinispan_4_0.xsd should you have any doubts)
The last problem is that for local caches, WF automatically enables certain optimizations when it's possible. When you redefine the cache programmatically, this optimization (simple cache) is set on. So you'd have to set
new ConfigurationBuilder().read(cache.getCacheConfiguration())
.simpleCache(false)
.invocationBatching().enable()

Error Injecting the JPA Entity Manager in WebSphere Liberty

I have inherited a legacy application that initially was built with WebSphere 6.1 and then was migrated to WebSphere 8.0 running with JPA 2.0 and openJPA without issues. We are migrating to WebSphere Liberty for strategic reasons. We first tested on WebSphere Classic 8.5.5.8 and JPA and the entity manger has no issues there. However, on Liberty 8.5.5.8 I get the following exception:
javax.ejb.EJBException: The java:comp/env/com.xxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved.
at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493)
.....
[err] Caused by:
[err] javax.ejb.EJBException: The java:comp/env/com.xxxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved.
[err] at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493)
[err] at [internal classes]
I had another EJB injection issue that was resolved through configuration of the binding files, however I am unable to resolve this issue. I have two applications that each have their own EAR files but both run in the same Liberty JVM. Application A runs the front end/UI logic while Application B is the back-end EJB / JPA interfaces. In the project facets the JPA application is set to 2.0 (I wanted 2.1 but based on another thread JPA 2.0 and EJB 3.1 are as high as I can go at the moment...See my other thread topic here -->Eclipse Juno and JPA 2.1 support).
Here is my server.xml file:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>javaee-7.0</feature>
<feature>localConnector-1.0</feature>
<feature>distributedMap-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>ssl-1.0</feature>
<feature>usr:webCacheMonitor-1.0</feature>
<feature>webCache-1.0</feature>
<feature>ldapRegistry-3.0</feature>
</featureManager>
<!-- Admin Center Config Start -->
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint host="*" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<keyStore id="defaultKeyStore" password="xxxxxx"/>
<basicRegistry id="basic">
<user name="admin" password="xxxxx"/>
<user name="nonadmin" password="xxxxxx"/>
</basicRegistry>
<administrator-role>
<user>admin</user>
</administrator-role>
<remoteFileAccess>
<writeDir>${server.config.dir}</writeDir>
</remoteFileAccess>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<enterpriseApplication id="CHNewCHRDMEAR" location="CHNewCHRDMEAR.ear" name="CHNewCHRDMEAR">
<application-bnd>
<security-role name="AllAuthenticated">
<special-subject type="ALL_AUTHENTICATED_USERS"/>
</security-role>
</application-bnd>
</enterpriseApplication>
<enterpriseApplication id="CHServiceEAR" location="CHServiceEAR.ear" name="CHServiceEAR"/>
<!-- JAAS Authentication Alias (Global) Config -->
<authData id="dbUser" password="{xor}MzhmJT06ajI=" user="dbUser"/>
<!-- JDBC Driver and Datasource Config -->
<library id="DB2JCC4Lib">
<fileset dir="C:\DB2\Jars" includes="db2jcc4.jar db2jcc_license_cisuz.jar"/>
</library>
<dataSource containerAuthDataRef="dbUser" id="CHTEST2" jndiName="jdbc/nextgen" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<dataSource id="CHTEST2_RO" jndiName="jdbc/nextgen_RO" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<!-- More in file, but no included...-->
</server>
Here is my persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="CHService" transaction-type="JTA">
<jta-data-source>jdbc/nextgen</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" /></properties></persistence-unit>
<persistence-unit name="CHServiceRO" transaction-type="JTA">
<jta-data-source>jdbc/nextgen_RO</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" />
</properties>
</persistence-unit>
</persistence>
I *believe that we are relying solely on injection to get the context for JPA jndi lookups but that is because I don't see in our code any call to an initial context for any JPA specific JNDI names. Below are my two anotated session beans from the EJB project:
a. The CHService Bean:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
#Local({ CHServiceLocal.class })
#Remote({ CHServiceRemote.class })
#Interceptors({ CHServiceLog.class })
#Resources({
#Resource(name = "jdbc/nextgen", mappedName = "jdbc/nextgen", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = javax.sql.DataSource.class),
#Resource(name = "services/cache/CHBluepages", mappedName = "services/cache/CHBluepages", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class),
#Resource(name = "services/cache/CHGeneric", mappedName = "services/cache/CHGeneric", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class) })
public class CHServiceBean extends AbstractCHServiceImpl implements
CHService {
#PersistenceContext(unitName = "CHService")
private EntityManager em;
b. The CHServiceRO bean:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
#Local({CHServiceLocalRO.class})
#Remote({CHServiceRemoteRO.class})
#Interceptors({CHServiceROLog.class})
#Resources({
#Resource(name="jdbc/nextgen_RO", mappedName="jdbc/nextgen_RO", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
#Resource(name="jdbc/nextgen", mappedName="jdbc/nextgen", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
#Resource(name="services/cache/CHBluepages", mappedName="services/cache/CHBluepages", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class),
#Resource(name="services/cache/CHGeneric", mappedName="services/cache/CHGeneric", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class)
})
public class CHServiceBeanRO implements CHServiceRO {
#PersistenceContext (unitName="CHServiceRO") private EntityManager em;
private CHServiceBase ch;
#PostConstruct
private void init() { ch = new CHServiceBase(em); }
Here is a snippet from the Web.xml of the front-end application calling the JPA application:
<resource-ref id="ResourceRef_1436377001246">
<res-ref-name>jdbc/nextgen</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref id="ResourceRef_1436377001247">
<res-ref-name>jdbc/nextgen_RO</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Based on the post from Gas on this topic: java.lang.ClassCastException,Getting Entitymanager Via JNDI Lookup
I also tried updating the web.xml with the following entries:
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA</persistence-unit-ref-name>
<persistence-unit-name>CHService</persistence-unit-name>
</persistence-unit-ref>
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA_RO</persistence-unit-ref-name>
<persistence-unit-name>CHServiceRO</persistence-unit-name>
</persistence-unit-ref>
and the Bean code with:
#PersistenceContext(name = "chJPA", unitName = "CHService")
and
#PersistenceContext (name="chJPA_RO", unitName="CHServiceRO")
Got the same error just with a different jndi name, ie The java:comp/env/chJPA reference of type javax.persistence.EntityManager for the CHServiceBean com.......etc etc.
Lastly, per this post: Error while accessing EntityManager - openjpa - WAS liberty profile
It seems that maybe I can't have the full JavaEE 7 feature and run JPA 2.0? Please advise!
As in the post you are referring to - you cannot have <feature>javaee-7.0</feature> together with JPA 2.0, as it enables 2.1, thats why you have conflicts.
So you have 2 options:
either use Java EE7 and JPA 2.1
or just enable required Java EE 6 features and then use JPA 2.0
Since you are migrating from WAS 8.0, which doesn't support Java EE7 for now, easier choice might be to use the second option.
So try to remove javee-7.0 feature, and add ejbLite-3.1 and jpa-2.0 and whatever you need more.
You are correct that you cannot have javaee-7.0 and the JPA 2.0 feature, as it enables the JPA 2.1 feature. So the answer Gas gave is correct.
I just wanted to point out since you said that you do want to go to JPA 2.1 eventually, once you work out your eclipse issues, that you should use the WebSphere Application Server Migration Toolkit to identify application changes needed when migrating from JPA 2.0 to JPA 2.1. The Liberty JPA 2.0 implementation is built on OpenJPA, whereas the JPA 2.1 implemtation is built on EclipseLink. The migration toolkit is downloadable for free on wasdev: https://developer.ibm.com/wasdev/downloads/#asset/tools-WebSphere_Application_Server_Migration_Toolkit

Correct way to make datasources/resources a deploy-time setting

I have a web-app that requires two settings:
A JDBC datasource
A string token
I desperately want to be able to deploy one .war to various different containers (jetty,tomcat,gf3 minimum) and configure these settings at application level within the container.
My code does this:
InitialContext ctx = new InitialContext();
Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env");
token = (String)envCtx.lookup("token");
ds = (DataSource)envCtx.lookup("jdbc/datasource")
Let's assume I've used the glassfish management interface to create two jdbc resources: jdbc/test-datasource and jdbc/live-datasource which connect to different copies of the same schema, on different servers, different credentials etc. Say I want to deploy this to glassfish with and point it at the test datasource, I might have this in my sun-web.xml:
...
<resource-ref>
<res-ref-name>jdbc/datasource</res-ref-name>
<jndi-name>jdbc/test-datasource</jndi-name>
</resource-ref>
...
but
sun-web.xml goes inside my war, right?
surely there must be a way to do this through the management interface
Am I even trying to do the right thing? Do other containers make this any easier? I'd be particularly interested in how jetty 7 handles this since I use it for development.
EDIT Tomcat has a reasonable way to do this:
Create $TOMCAT_HOME/conf/Catalina/localhost/webapp.xml with:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true">
<!-- String resource -->
<Environment name="token" value="value of token" type="java.lang.String" override="false" />
<!-- Linking to a global resource -->
<ResourceLink name="jdbc/datasource1" global="jdbc/test" type="javax.sql.DataSource" />
<!-- Derby -->
<Resource name="jdbc/datasource2"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.apache.derby.jdbc.EmbeddedDataSource"
url="jdbc:derby:test;create=true"
/>
<!-- H2 -->
<Resource name="jdbc/datasource3"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.h2.jdbcx.JdbcDataSource"
url="jdbc:h2:~/test"
username="sa"
password=""
/>
</Context>
Note that override="false" means the opposite. It means that this setting can't be overriden by web.xml.
I like this approach because the file is part of the container configuration not the war, but it's not part of the global configuration; it's webapp specific.
I guess I expect a bit more from glassfish since it is supposed to have a full web admin interface, but I would be happy enough with something equivalent to the above.
For GF v3, you may want to try leveraging the --deploymentplan option of the deploy subcommand of asadmin. It is discussed on the man page for the deploy subcommand.
We had just this issue when migrating from Tomcat to Glassfish 3. Here is what works for us.
In the Glassfish admin console, configure datasources (JDBC connection pools and resources) for DEV/TEST/PROD/etc.
Record your deployment time parameters (in our case database connect info) in properties file. For example:
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
Each web app can load the same database properties file.
Lookup the JDBC resource as follows.
import java.sql.Connection;
import javax.sql.DataSource;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* #param resourceName the resource name of the connection pool (eg jdbc/dbdev)
* #return Connection a pooled connection from the data source
* associated with resourceName
* #throws NamingException will be thrown if resource name is not found
*/
public Connection getDatabaseConnection(String resourceName)
throws NamingException, SQLException {
Context initContext = new InitialContext();
DataSource pooledDataSource = (DataSource) initContext.lookup(resourceName);
return pooledDataSource.getConnection();
}
Note that this is not the usual two step process involving a look up using the naming context "java:comp/env." I have no idea if this works in application containers other than GF3, but in GF3 there is no need to add resource descriptors to web.xml when using the above approach.
I'm not sure to really understand the question/problem.
As an Application Component Provider, you declare the resource(s) required by your application in a standard way (container agnostic) in the web.xml.
At deployment time, the Application Deployer and Administrator is supposed to follow the instructions provided by the Application Component Provider to resolve external dependencies (amongst other things) for example by creating a datasource at the application server level and mapping its real JNDI name to the resource name used by the application through the use of an application server specific deployment descriptor (e.g. the sun-web.xml for GlassFish). Obviously, this is a container specific step and thus not covered by the Java EE specification.
Now, if you want to change the database an application is using, you'll have to either:
change the mapping in the application server deployment descriptor - or -
modify the configuration of the existing datasource to make it points on another database.
Having an admin interface doesn't really change anything. If I missed something, don't hesitate to let me know. And just in case, maybe have a look at this previous answer.