<?xml version="1.0" encoding="UTF-8"?>
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
xmlns='http://www.ehcache.org/v3'
xsi:schemaLocation="
http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.1.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.1.xsd">
<service>
<jsr107:defaults enable-management="false" enable-statistics="true"/>
</service>
<cache alias="mySlidingExpiryJCache">
<key-type>java.lang.Long</key-type>
<expiry>
<tti unit="seconds">2</tti>
</expiry>
<resources>
<heap unit="entries">200</heap>
</resources>
<jsr107:mbeans enable-statistics="true"/>
</cache>
</config>
I want to show statistics by extracting the MBean, however I don't know how, because on the net I can see only the bean injected programmatically (see also this SO question).
StatisticsService statisticsService = new DefaultStatisticsService();
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.using(statisticsService)
.build();
cacheManager.init();
Any advice ?
You enabled JSR107/JCache statistics. Those are available via JMX. If you want to access those JMX beans programmatically, you can do something like this:
Cache cache = // a JSR107 cache
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("javax.cache:type=CacheStatistics," +
"CacheManager=" + cache.getCacheManager().getURI().toString() +
",Cache=" + mbeanSafe(cache.getName()));
long hits = mBeanServer.getAttribute(name, "CacheHits");
Be aware that the JCache Cache is created differently then you do it in your question. See the extensive documentation here: https://www.ehcache.org/documentation/3.0/107.html
JSR107/JCache is a standard API that many Java caches support. It also includes the exposure of statistics via JMX. The available metrics are defined at: https://github.com/jsr107/jsr107spec/blob/master/src/main/java/javax/cache/management/CacheStatisticsMXBean.java
Related
I really want to use container managed transactions with JPA and therefor would go the easy way of having the data source creation within the server.xml and then using the #PersistenceContext within my code.
The problem I currently face - and maybe I am thinking too complicated - is the fact that I get the credentials during runtime in my Cloud Foundry environment as VCAP_SERVICES system environment variable.
This VCAP_SERVICES variable contains a big JSON with the necessary credentials. Therefor I would first have to extract the corresponding JSON within this and pass it then as property.
My initial idea was to use converters for this case returning the values out of the JSON so that they can be used. But it seems like this is not possible within a defined configuration xml file.
What I for sure want to prevent is the "injection" of something doing on my own like having a property file and copying the values from the different environments DEV, TEST, PROD in there as the Cloud Foundry environment is already doing the job for me.
So the question is:
How can I get the credentials from the VCAP_SERVICES system environment variable into the server.xml configuration? Remember: I really have to parse the VCAP_SERVICES variable as this is JSON and extract the values.
<?xml version="1.0" encoding="UTF-8"?>
<server description="Config example">
<featureManager>
<feature>javaee-8.0</feature>
<feature>mpMetrics-1.1</feature>
<feature>monitor-1.0</feature>
</featureManager>
<!-- Postgres config-example-db definition -->
<dataSource id="DefaultDataSource" jndiName="jdbc/config-example" jdbcDriverRef="postgresql-driver"
type="javax.sql.ConnectionPoolDataSource" transactional="true">
<properties serverName="config-example-db" portNumber="5432"
databaseName="postgres"
user="${config-example.db.username}"
password="${config-example.db.password}"/>
</dataSource>
<basicRegistry id="basic" realm="MicroProfileMetrics">
<user name="admin" password="adminadmin"/>
<user name="nonadmin" password="guest"/>
</basicRegistry>
<administrator-role>
<user>admin</user>
</administrator-role>
</server>
For many services the liberty buildpack will auto-config the server.xml.
postgresql is one of them. See:
https://github.com/cloudfoundry/ibm-websphere-liberty-buildpack/blob/master/docs/services/postgresql.md
Additionally, for many services, the buildpack will create environment variables that are then accessible by the application.
For example, binding a cloudantNoSQL service to an app results in the following credentials in VCAP_SERVICES:
{
"binding_name": null,
"credentials": {
"apikey": "<apikey>",
"host": "<host>-bluemix.cloudantnosqldb.test.appdomain.cloud",
"iam_apikey_description": "Auto-generated for binding <host>",
"iam_apikey_name": "Cloudant-sd",
"iam_role_crn": "crn:v1:bluemix:public:iam::::serviceRole:Writer",
"iam_serviceid_crn": "crn:v1:staging:public:iam-identity::<id>::serviceid:ServiceId-<serviceid>",
"url": "https://<host>-bluemix.cloudantnosqldb.test.appdomain.cloud",
"username": "<username>-bluemix"
},
The buildpack will then create variables in the runtime-vars.xml:
<variable name='cloud.services.Cloudant-sd.label' value='cloudantNoSQLDB'/>
<variable name='cloud.services.Cloudant-sd.plan' value='Lite'/>
<variable name='cloud.services.Cloudant-sd.name' value='Cloudant-sd'/>
<variable name='cloud.services.Cloudant-sd.instance_name' value='Cloudant-sd'/>
<variable name='cloud.services.Cloudant-sd.connection.apikey' value='<apikey'/>
<variable name='cloud.services.Cloudant-sd.connection.host' value='<host>-bluemix.cloudantnosqldb.test.appdomain.cloud'/>
<variable name='cloud.services.Cloudant-sd.connection.iam_apikey_description' value='Auto-generated for binding <host>'/>
<variable name='cloud.services.Cloudant-sd.connection.iam_apikey_name' value='Cloudant-sd'/>
<variable name='cloud.services.Cloudant-sd.connection.iam_role_crn' value='crn:v1:bluemix:public:iam::::serviceRole:Writer'/>
<variable name='cloud.services.Cloudant-sd.connection.iam_serviceid_crn' value='crn:v1:staging:public:iam-identity::<id>::serviceid:ServiceId-<serviceid'/>
<variable name='cloud.services.Cloudant-sd.connection.url' value='https://<host>-bluemix.cloudantnosqldb.test.appdomain.cloud'/>
<variable name='cloud.services.Cloudant-sd.connection.username' value='<username>-bluemix'/>
See https://cloud.ibm.com/docs/runtimes/liberty?topic=liberty-options_for_pushing#accessing_info_of_bound_services.
I am trying to deploy an ejb but would like to provide custom jndi name for it.
I created below: weblogic-ejb-jar.xml
`
<?xml version='1.0' encoding='UTF-8'?>
<weblogic-ejb-jar xmlns="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar http://xmlns.oracle.com/weblogic/weblogic-ejb-jar/1.2/weblogic-ejb-jar.xsd">
<weblogic-enterprise-bean>
<ejb-name>test</ejb-name>
<jndi-name>ejb/test</jndi-name>
<enable-call-by-reference>true</enable-call-by-reference>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
`
But when I try to look up bean using this jndi name, I get javax.naming.NameNotFoundException.
Is there any configuration that I am missing here?
It is likely that you are not looking up the bean correctly. You could try the following.
Context initialContext = new InitialContext();
test testInstance = (test)
initialContext.lookup("java:comp/env/ejb/test");
I can get items out of the cache manager by using
cachemanager.getCache("cachename").get(cacheKey)
How do I add a new cache via the cache manager? There appears to be only getCache() and getCacheNames().
There is getCache("newcachename").put(cacheKey) but that fails as "newcachename" doesn't exist.
Sorted, my fault. I didnt add the new cache details to the ehcache.xml file.
<cache name="newcachename" maxElementsInMemory="10000"
eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="300"
overflowToDisk="false" diskPersistent="false"/>
Once I added this I could use
getCache("newcachename").put(cacheKey, "value to cache")
Thanks all for your assistance.
I don't know exactly what you configuration looks like so I can't give a more detailed explanation, but I have successfully used multiple caches using Spring's CompositeCacheManager
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="newcachename" />
</set>
Have you set up this cache for this cacheName in the configurations?
I have to execute long running threads in a WebLogic Bea 10.0 M1 server environment. I tried to use WorkManagers for this. Using an own WorkManager allows me to specify my own thread timeout (MaxThreadStuckTime) instead of adjusting the timeout for the whole business application.
My setup is as follows:
weblogic-ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
<resource-description>
<res-ref-name>myWorkManager</res-ref-name>
<jndi-name>wm/myWorkManager</jndi-name>
</resource-description>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
weblogic-application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic xmlns="http://www.bea.com/ns/weblogic/90" xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
http://www.bea.com/ns/weblogic/90/weblogic.xsd">
<work-manager>
<name>myWorkManager</name>
<ignore-stuck-threads>1</ignore-stuck-threads>
</work-manager>
</weblogic>
and the Bean:
import javax.annotation.Resource;
import javax.ejb.Stateful;
import weblogic.work.WorkManager;
#Stateful(mappedName = "TestBean")
public class TestBean implements TestBeanRemote {
#Resource(name = "myWorkManager")
private WorkManager myWorkManager;
public void test() {
myWorkManager.schedule(new Runnable() {
public void run() {
while (true) {
System.out.println("test: +++++++++++++++++++++++++");
try {
Thread.sleep(45000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
When I try to deploy this things, the server gives me the following exceptions:
[EJB:011026]The EJB container failed while creating the java:/comp/env namespace for this EJB deployment.
weblogic.deployment.EnvironmentException: [EJB:010176]The resource-env-ref 'myWorkManager' declared in the ejb-jar.xml descriptor has no JNDI name mapped to it. The resource-ref must be mapped to a JNDI name using the resource-description element of the weblogic-ejb-jar.xml descriptor.
I try to figure out how to access / use WorkMangers for days now, and still get this or that as an exception. Very frustrating!
Thanks in advance!
You need to remove the WorkManager refrence from your weblogic-ejb-jar.xml, this refenece should go to ejb-jar.xml.
Infact I doubt if Weblogic schema definition "weblogic-ejb-jar.xsd" will allow you to add a reference element, you must be getting xsd validation errors.
anyways, get rid of the element
resource-description from weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
<resource-description>
<res-ref-name>myWorkManager</res-ref-name>
<jndi-name>wm/myWorkManager</jndi-name>
</resource-description>
</weblogic-enterprise-bean>
it will look like this
weblogic-ejb-jar.xml
<weblogic-enterprise-bean>
<ejb-name>TestBean</ejb-name>
</weblogic-enterprise-bean>
your workManager reference will go to ejb-jar.xml like this.
ejb-jar.xml
<enterprise-beans>
<session>
<ejb-name>TestBean</ejb-name>
<ejb-class>com.xxx.TestBean</ejb-class> <!-- your package com.xxx-->
<resource-ref>
<res-ref-name>myWorkManager</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</session>
</enterprise-beans>
Now to get WorkManager from JNDI I'm doing
InitialContext ctx = new InitialContext();
this.workManager = (WorkManager) ctx.lookup("java:comp/env/myWorkManager");
but I belive annotation will work equally well.
#Resource(name = "myWorkManager")
my weblogic-application.xml looks same as shared above
<weblogic>
<work-manager>
<name>myWorkManager</name>
<ignore-stuck-threads>1</ignore-stuck-threads>
</work-manager>
This is working for me .. let me know if needed I can share my full code.
you can view your WorkManager and load on it by going to Weblogic Admin Console
Home—>Deployments—>yourApp—>Monitoring(Tab)—>WorkLoad(Tab)”
You need to name your work manager. The way we do it is in our Ear project EarContent/META-INF/weblogic-application.xml
<wls:work-manager>
<wls:name>wmBatch</wls:name>
<wls:ignore-stuck-threads>true</wls:ignore-stuck-threads>
</wls:work-manager>
(which you appear to have done)
and then we use the annotations to set the manager:
#MessageDriven(ejbName =..., dispatchPolicy = "wmBatch")
And then there is no coding around getting the work manager. This might work for you.
BEA (together with IBM) have developed a framework specifically for managing long-running tasks in a Java EE environment. Take a look at CommonJ.
The Spring Framework offers some convenience classes around this framework.
I'm trying to use this method for receiving mail in our EJB3 app. In short, that means creating an MDB with the following annotations:
#MessageDriven(activationConfig = { #ActivationConfigProperty(propertyName = "mailServer", propertyValue = "imap.company.com"),
#ActivationConfigProperty(propertyName = "mailFolder", propertyValue = "INBOX"),
#ActivationConfigProperty(propertyName = "storeProtocol", propertyValue = "imap"),
#ActivationConfigProperty(propertyName = "debug", propertyValue = "false"),
#ActivationConfigProperty(propertyName = "userName", propertyValue = "username"),
#ActivationConfigProperty(propertyName = "password", propertyValue = "pass") })
#ResourceAdapter("mail-ra.rar")
#Name("mailMessageBean")
public class MailMessageBean implements MailListener {
public void onMessage(final Message msg) {
...snip...
}
}
I have this working, but the situation is less than ideal: The hostname, username and password are hardcoded. Short of using ant and build.properties to replace those values before compilation, I don't know how to externalize them.
It would be ideal to use an MBean, but I have no idea how to get the values from the MBean to the MDB configuration.
How should I do this?
You can externalise the annotations into the ejb-jar.xml that you deploy in the META-INF of your jar file as follows:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0">
<enterprise-beans>
<message-driven>
<ejb-name>YourMDB</ejb-name>
<ejb-class>MailMessageBean</ejb-class>
<activation-config>
<activation-config-property>
<activation-config-property-name>username</activation-config-property-name>
<activation-config-property-value>${mdb.user.name}</activation-config-property-value>
</activation-config-property>
...
...
</activation-config>
</message-driven>
</enterprise-beans>
Then you can set the mdb.user.name value as a system property as part of the command line to your application server using -Dmdb.user.name=theUserName and it will magically get picked up by the mdb.
Hope that helps.
As of JBoss AS 5.1 at least, you can use AOP to configure the #ActivationConfigProperties. I discovered this by looking at the examples that jboss provides here. This is useful if you do not want your username and passwords available to the entire container in a systems property, or if you are like me and never, I repeat NEVER, want to deploy an artifact with a username/password in it. Any how, here is the jist...
Annotate the mdb like this...
...
#MessageDriven
#AspectDomain("TestMDBean")
public class TestMDBean implements MessageListener {
...
Then add a ${whatever}-aop.xml to the deploy dir with internals like below. I left the original comments in there in case Jaikiran does make the changes mentioned...
Note: the annotation must be on one
line only.
<?xml version="1.0" encoding="UTF-8"?>
<aop xmlns="urn:jboss:aop-beans:1.0">
<!-- TODO: Jaikiran - These interceptor declarations need not be here since they
are already declared through the ejb3-interceptors-aop.xml. Duplicating them leads to
deployment errors. However, if this custom-ejb3-interceptors-aop.xml needs to be
independent, then we must find a better way of declaring these. Right now, commenting these
out, can be looked at later. -->
<!--
<interceptor class="org.jboss.ejb3.AllowedOperationsInterceptor" scope="PER_VM"/>
<interceptor class="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory" scope="PER_CLASS"/>
<interceptor class="org.jboss.ejb3.stateless.StatelessInstanceInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory" scope="PER_CLASS_JOINPOINT"/>
<interceptor factory="org.jboss.aspects.tx.TxInterceptorFactory" scope="PER_CLASS_JOINPOINT"/>
-->
<domain name="TestMDBean" extends="Message Driven Bean" inheritBindings="true">
<annotation expr="!class(#org.jboss.ejb3.annotation.DefaultActivationSpecs)">
#org.jboss.ejb3.annotation.DefaultActivationSpecs (value={#javax.ejb.ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), #javax.ejb.ActivationConfigProperty(propertyName="destination", propertyValue="queue/MyQueue"), #javax.ejb.ActivationConfigProperty(propertyName="user", propertyValue="testusr"), #javax.ejb.ActivationConfigProperty(propertyName="password", propertyValue="testpwd")})
</annotation>
</domain>
</aop>