Coherence: Simple custom AddressProvider not working - oracle-coherence

I was trying to use address-provider for well-known-addresses configuration. But it is not working.
Here's my config file:
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config coherence-operational-config.xsd">
<cluster-config>
<unicast-listener>
<well-known-addresses>
<address-provider>
<class-name>xilu.scratch.coherence.MyAddressProvider</class-name>
</address-provider>
<!--
<socket-address id="1">
<address>127.0.0.1</address>
<port>8888</port>
</socket-address>
-->
</well-known-addresses>
<address>127.0.0.1</address>
<port>8888</port>
<port-auto-adjust system-property="tangosol.coherence.localport.adjust">
false
</port-auto-adjust>
</unicast-listener>
</cluster-config>
</coherence>
And here's my address provider:
package xilu.scratch.coherence;
import java.net.InetSocketAddress;
/**
* Created by xxilu on 5/18/16.
*/
public class MyAddressProvider implements com.tangosol.net.AddressProvider {
private String[] addressList = {
"127.0.0.1",
};
private int index = 0;
#Override
public InetSocketAddress getNextAddress() {
if(index >= 1) {
return null;
}
String addressText = addressList[index];
index++;
InetSocketAddress addr = new InetSocketAddress(addressText, 8888);
return addr;
}
#Override
public void accept() {
}
#Override
public void reject(Throwable throwable) {
}
}
It looks very trivial, but the cluster cannot be formed.
I get log like this:
/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/bin/java -Dtangosol.coherence.log.level=9 -Djava.net.preferIPv4Stack=true -Didea.launcher.port=7537 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 15.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home/lib/tools.jar:/Users/xxilu/Projects/scratch/Coherence1/out/production/Coherence1:/Users/xxilu/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar:/Users/xxilu/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.fasterxml.jackson.core.jackson-core.jar:/Users/xxilu/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider.jar:/Users/xxilu/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.fasterxml.jackson.core.jackson-databind.jar:/Users/xxilu/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.fasterxml.jackson.core.jackson-annotations.jar:/Users/xxilu/Oracle/Middleware/Oracle_Home/oracle_common/modules/com.fasterxml.jackson.module.jackson-module-jaxb-annotations.jar:/Applications/IntelliJ IDEA 15.app/Contents/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain xilu.scratch.coherence.HelloWorld
2016-05-19 00:19:42.117/1.064 Oracle Coherence 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Loaded operational configuration from "jar:file:/Users/xxilu/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2016-05-19 00:19:42.198/1.136 Oracle Coherence 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Loaded operational overrides from "jar:file:/Users/xxilu/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
2016-05-19 00:19:42.258/1.196 Oracle Coherence 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Loaded operational overrides from "file:/Users/xxilu/Projects/scratch/Coherence1/out/production/Coherence1/tangosol-coherence-override.xml"
2016-05-19 00:19:42.268/1.206 Oracle Coherence 12.2.1.0.0 <D5> (thread=pool-1-thread-1, member=n/a): Optional configuration override "cache-factory-config.xml" is not specified
2016-05-19 00:19:42.269/1.207 Oracle Coherence 12.2.1.0.0 <D5> (thread=pool-1-thread-1, member=n/a): Optional configuration override "cache-factory-builder-config.xml" is not specified
2016-05-19 00:19:42.269/1.208 Oracle Coherence 12.2.1.0.0 <D5> (thread=pool-1-thread-1, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
2016-05-19 00:19:42.270/1.208 Oracle Coherence 12.2.1.0.0 <D6> (thread=pool-1-thread-1, member=n/a): Loaded edition data from "jar:file:/Users/xxilu/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/coherence-grid.xml"
Oracle Coherence Version 12.2.1.0.0 Build 60603
Grid Edition: Development mode
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
2016-05-19 00:19:42.798/1.736 Oracle Coherence GE 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Loaded FMW commons version: 12.2.1-0-0-SNAPSHOT b60603
2016-05-19 00:19:42.885/1.823 Oracle Coherence GE 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Loaded cache configuration from "file:/Users/xxilu/Projects/scratch/Coherence1/out/production/Coherence1/coherence-cache-config.xml"
2016-05-19 00:19:43.539/2.477 Oracle Coherence GE 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): The cluster name has not been configured, a value of "xxilu's cluster" has been automatically generated
2016-05-19 00:19:43.567/2.506 Oracle Coherence GE 12.2.1.0.0 <Info> (thread=pool-1-thread-1, member=n/a): Created cache factory com.tangosol.net.ExtensibleConfigurableCacheFactory
2016-05-19 00:19:44.020/2.958 Oracle Coherence GE 12.2.1.0.0 <Warning> (thread=pool-1-thread-1, member=n/a): Local address "127.0.0.1" is a loopback address; this cluster node will not connect to nodes located on different machines
2016-05-19 00:19:44.069/3.008 Oracle Coherence GE 12.2.1.0.0 <D4> (thread=pool-1-thread-1, member=n/a): TCMP bound to /127.0.0.1:8888 using SystemDatagramSocketProvider
And it stops there.
If I change the address provider to the socket-address style (as commented out in the config), things will work.

[I posted the question earlier for documentation purpose. I've spent 10 hours debugging this issue and I finally found the root cause].
After spending 10 hours, I found the root cause.
There's one very subtle detail about AddressProvider implementation. The document says getNextAddress should return a null to indicate all addresses are exhausted. But there's one important thing it didn't say: after returning the null, the next call to getNextAddress should look like the very first call to this object. In another word, if you view getNextAddress as an iterator, the iterator need to reset after returning the terminating null.
So changing MyAddressProvider from this:
#Override
public InetSocketAddress getNextAddress() {
if(index >= 1) {
return null;
}
}
To this:
#Override
public InetSocketAddress getNextAddress() {
if(index >= 1) {
index = 0;
return null;
}
}
Things will work.
Hopefully this can help people hitting similar issue.

Related

How can I connect oracle coherence remote cluster using java

There is a coherence cluster (with a cache by name mycache) that is runnig on ip address xxx.xxx.xxx.xxx (not localhost). I am trying to connect it and read from cache using java.
This is my Reader class:
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class Reader {
public static void main(String[] args) {
NamedCache cache = CacheFactory.getCache("mycache");
System.out.println("Value in cache is: " + cache.get("key1"));
}
}
I am using Intellij IDEA, in vm option for reader I added this line:
-Dtangosol.coherence.cacheconfig=mycache.xml
and this is mycache.xml file:
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
coherence-operational-config.xsd"
xml-override="{tangosol.coherence.override /tangosol-coherence-override-{mode}.xml}">
<cluster-config>
<member-identity>
<cluster-name>RemoteCluster</cluster-name>
</member-identity>
<unicast-listener>
<well-known-addresses>
<socket-address id="1">
<address>192.168.104.160</address>
<port>8088</port>
</socket-address>
</well-known-addresses>
</unicast-listener>
</cluster-config>
</coherence>
when I run reader.main() I get this exception:
Problem : An ElementProcessor could not be located for the element [coherence]
Advice : The specified element is unknown to the NamespaceHandler implementation. Perhaps the xml element is foreign to the Xml Namespace?
at com.tangosol.util.Base.ensureRuntimeException(Base.java:286)
at com.tangosol.net.ScopedCacheFactoryBuilder.instantiateFactory(ScopedCacheFactoryBuilder.java:433)
at com.tangosol.net.ScopedCacheFactoryBuilder.buildFactory(ScopedCacheFactoryBuilder.java:385)
at com.tangosol.net.ScopedCacheFactoryBuilder.getFactory(ScopedCacheFactoryBuilder.java:267)
at com.tangosol.net.ScopedCacheFactoryBuilder.getConfigurableCacheFactory(ScopedCacheFactoryBuilder.java:119)
at com.tangosol.net.CacheFactory.getConfigurableCacheFactory(CacheFactory.java:127)
at com.tangosol.net.CacheFactory.getCache(CacheFactory.java:205)
at com.tangosol.net.CacheFactory.getCache(CacheFactory.java:182)
at Reader.main(Reader.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: com.tangosol.config.ConfigurationException: Configuration Exception
-----------------------
Problem : An ElementProcessor could not be located for the element [coherence]
Advice : The specified element is unknown to the NamespaceHandler implementation. Perhaps the xml element is foreign to the Xml Namespace?
it looks like the problem in the mycache.xml. Those elements used when you want to set up cluster member, while you want to connect a client.
Assuming that "mycache" schema exists on remote cluster try to change the mycache.xml with following:
<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config xmlns="http://schemas.tangosol.com/cache">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>mycache</cache-name>
<scheme-name>extend-dist</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<remote-cache-scheme>
<scheme-name>extend-dist</scheme-name>
<service-name>ExtendTcpCacheService</service-name>
<initiator-config>
<tcp-initiator>
<remote-addresses>
<socket-address>
<address>192.168.104.160</address>
<port>8088</port>
</socket-address>
</remote-addresses>
</tcp-initiator>
<outgoing-message-handler>
<request-timeout>20s</request-timeout>
</outgoing-message-handler>
</initiator-config>
</remote-cache-scheme>
</caching-schemes>
</cache-config>
Note: if remote cluster uses POF serialization for mycache you'll have to add POF mapping and configuration -Dtangosol.pof.enabled=true
Your xml file is an operational config rather than cache config. To use this configuration, run your programm with:
-Dtangosol.coherence.override=mycache.xml
instead of:
-Dtangosol.coherence.cacheconfig=mycache.xml
BTW you should rename mycache.xml to e.g. operational-config.xml in order to not confuse it with cache configuration.

CouchBaseTemplate Connection issue

I have the Following CouchBase Template Bean:
#PostConstruct
public void initIt() throws Exception {
if(couchbaseDisabled)
return;
couchbaseClient= new CouchbaseClient(
bootstrapUris(Arrays.asList(hosts.split(","))),
CouchbaseConstants.BUCKET,
""
);
couchbaseTemplate();
}
public void couchbaseTemplate() throws Exception {
logger.info("Enabling CouchBase Template");
couchbaseTemplate= new CouchbaseTemplate(couchbaseClient);
//couchbaseTemplate.
}
and
#PreDestroy
public void cleanup() throws Exception {
logger.info("Closing couchbase connection.");
if (couchbaseClient != null) {
couchbaseClient.shutdown();
couchbaseTemplate=null;
couchbaseClient=null;
}
}
While the Server is being Shut Down i am geting the Following Logs:
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#5ddaa15d]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#3c9810ce]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#23776376]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#7322ea2a]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:32 PM org.apache.coyote.http11.Http11Protocol destroy
INFO: Stopping Coyote HTTP/1.1 on http-8099
What can be Done Here?
Ok so you have both SDK 1.4.x and 2.x running in your application (since you have com.couchbase.client:java-client in your pom).
The thread leak message comes from the later. You must have instantiated a Cluster somewhere (as in com.couchbase.client.java.Cluster).
Make sure to also clean it up at the end of the application's lifecycle by calling cluster.disconnect() (I guess from a #PreDestroy method, as you did for the CouchbaseClient).
If you also created a custom CouchbaseEnvironment, you have to also properly shut it down (in the same method as the Cluster cleanup) by calling environment.shutdownAsync().toBlocking().single().
Make sure to use the latest version of the 2.x SDK as some older versions had bugs relative to proper thread cleanup on shutdown (see JCBC-773 and JVMCBC-251 issues).

How to launch local DynamoDB programmatically?

I am able to launch a local DynamoDB server from bash through this command:
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb &
Is there not a pure-java way to start the server in one's code? I don't mean a java callout to the shell through the Process object but a way such that when I run my app, the server starts, and when my app is killed, the server is killed.
I can live with an embedded database if such a mode exists, though something that reflects server consistency semantics would be ideal.
EDIT: September 23rd 2015
There was an announcement on Aug 3, 2015 that now adds the ability to have an embedded DynamoDB local running in the same process. You can add a Maven test dependency and use one of the ways below to run it.
<!--Dependency:-->
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>DynamoDBLocal</artifactId>
<version>[1.11,2.0)</version>
</dependency>
</dependencies>
<!--Custom repository:-->
<repositories>
<repository>
<id>dynamodb-local-oregon</id>
<name>DynamoDB Local Release Repository</name>
<url>https://s3-us-west-2.amazonaws.com/dynamodb-local/release</url>
</repository>
</repositories>
And here is an example taken from the awslabs/aws-dynamodb-examples Github repository:
AmazonDynamoDB dynamodb = null;
try {
// Create an in-memory and in-process instance of DynamoDB Local that skips HTTP
dynamodb = DynamoDBEmbedded.create().amazonDynamoDB();
// use the DynamoDB API with DynamoDBEmbedded
listTables(dynamodb.listTables(), "DynamoDB Embedded");
} finally {
// Shutdown the thread pools in DynamoDB Local / Embedded
if(dynamodb != null) {
dynamodb.shutdown();
}
}
// Create an in-memory and in-process instance of DynamoDB Local that runs over HTTP
final String[] localArgs = { "-inMemory" };
DynamoDBProxyServer server = null;
try {
server = ServerRunner.createServerFromCommandLineArgs(localArgs);
server.start();
dynamodb = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
// we can use any region here
new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();
// use the DynamoDB API over HTTP
listTables(dynamodb.listTables(), "DynamoDB Local over HTTP");
} finally {
// Stop the DynamoDB Local endpoint
if(server != null) {
server.stop();
}
}
Old answer
Like you said, there is currently no built-in way from DynamoDBLocal or the SDK to do this right now. It would be nice if there was an embedded DynamoDBLocal that you could start up in the same process.
Here is a simple workaround/solution using java.lang.Process to start it up and shut it down programmatically in case others are interested.
Documentation for DynamoDBLocal can be found here and here are the current definition of the arguments:
-inMemory — Run in memory, no file dump
-port 4000 — Communicate using port 4000.
-sharedDb — Use a single database file, instead of separate files for each credential and region
Note that this is using the most recent version of DynamoDBLocal as of August 5th, 2015.
final ProcessBuilder processBuilder = new ProcessBuilder("java",
"-Djava.library.path=./DynamoDBLocal_lib",
"-jar",
"DynamoDBLocal.jar",
"-sharedDb",
"-inMemory",
"-port",
"4000")
.inheritIO()
.directory(new File("/path/to/dynamo/db/local"));
final Process process = processBuilder.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Shutdown DynamoDBLocal");
process.destroy();
try {
process.waitFor(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("Process did not terminate after 3 seconds.");
}
System.out.println("DynamoDBLocal isAlive=" + process.isAlive());
}
});
// Do some stuff
Write a gradle task to extract the Dynamodb-Local zip and now you can use https://github.com/marcoVermeulen/gradle-spawn-plugin gradle plugin to launch the dynamodb local. It is very easy to use and no need to do any process builder magic.
Sample code -
// to start dynamodb-local
task launch(type: SpawnProcessTask) {
println("Launching....")
command "java -Djava.library.path=/location/to/dynamodb-local/DynamoDBLocal_lib -jar /location/to/dynamodb-local/DynamoDBLocal.jar -inMemory -delayTransientStatuses"
ready "Initializing DynamoDB Local"
}
// to stop dynamodb-local process
task stop(type: KillProcessTask)

The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped

I've seen few similar issues on stackoverflow but i could not figure out how i can solve my problem. After adding Spring Security to my Spring MVC project i got following exception:
Jul 20, 2014 3:18:04 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Here is my mysql-connecter in the pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
Here are classes that i've added:
#Component
#Transactional
public class UserDetailsServiceImpl implements UserDetailsService{
#Autowired
private UserDAO userDAO;
#Autowired
private UserAssembler userAssembler;
private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
#Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
User user = userDAO.findByEmail(username);
if(null == user) throw new UsernameNotFoundException("User not found");
return userAssembler.buildUserFromUser(user);
}
}
and assembler
#Service("assembler")
public class UserAssembler {
#Autowired
private UserDAO userDAO;
#Transactional(readOnly = true)
public User buildUserFromUser(net.viralpatel.contact.model.User user) {
String role = "ROLE_USER";//userEntityDAO.getRoleFromUserEntity(userEntity);
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new GrantedAuthorityImpl(role));
return new User(user.getLogin(), user.getPassword(), true, true, true, true, authorities);
}
}
Here is my spring-security.xml
<beans:bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />
<http auto-config="true">
<intercept-url pattern="/account/*" access="ROLE_ADMIN" />
<form-login login-page="/login" default-target-url="/account/overview" authentication-failure-url="/login?error=true"/>
<remember-me/>
</http>
<beans:bean id="myUserDetailsService" class="net.viralpatel.contact.service.UserDetailsServiceImpl" />
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailsService" />
</authentication-manager>
EDITED:
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /opt/idea-IU-135.909/bin::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Jul 20, 2014 3:58:36 PM org.apache.catalina.core.JreMemoryLeakPreventionListener lifecycleEvent
SEVERE: Failed to load class com.mysql.jdbc.NonRegisteringDriver during Tomcat start to prevent possible memory leaks.
java.lang.ClassNotFoundException: com.mysql.jdbc.NonRegisteringDriver
Your application doesn't have a flaw. It is the design of JDBC. The JDBC driver gets loaded and registered by the webapp when it creates a database connection for the first time.
That means that the driver is loaded with the web application class loader. On undeployment the driver doesn't get deregistered which in turn prevents your webapp classes from GC. That creates effectively a memory leak.
To prevent this particular memory leak you should edit your tomcat/conf/server.xml and change
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
to
<Listener
className="org.apache.catalina.core.JreMemoryLeakPreventionListener"
classesToInitialize="com.mysql.jdbc.NonRegisteringDriver" />
With mysql-connector-java-8.0.x use com.mysql.cj.jdbc.NonRegisteringDriver instead
Exclude the JDBC driver from your webapp artifact and put it into the tomcat/lib directory.
Now the JDBC driver gets loaded by Tomcat on startup and isn't linked to any webapps class loader.
Why should I modify the server.xml?
Another memory leaks manifests due to MySQL's 'Abandoned connection cleanup thread'. This thread starts with the first request and holds a reference to the webapp's classloader. With classesToInitialize you can prevent this memory leak too.
References:
org.apache.catalina.core.JreMemoryLeakPreventionListener tomcat-doc v7.0
AbandonedConnectionCleanupThread notes in v5.1.41
com.mysql.jdbc.NonRegisteringDriver source v5.1
com.mysql.cj.jdbc.NonRegisteringDriver source v8.0
mysql-connector-java changes in v8.0
What I did was just to put the mysql-connector-java-5.1.31-bin.jar in $CATALINA_HOME/lib. No modifications to server.xml.

OpenEJB : Configuring MDBs with custom ConnectionFactory

As described in OpenEJB docs, we can configure JMS connection factory and queues, and they will appear in JNDI as:
openejb:Resource/MyJmsConnectionFactory,
openejb:Resource/MyQueue
Given those JNDI entries, how can I tell to MDB to use them?
Is it possible to change JNDI name, for example ConnectionFactory to appear as java:/ConnectionFactory
or ConnectionFactory
Things work differently than you may be imagining. Specifying that an MDB is tied to a javax.jms.Queue and the name of that queue is part of the EJB specification and done via the ActivationConfig, like so:
#MessageDriven(activationConfig = {
#ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(
propertyName = "destination",
propertyValue = "FooQueue")})
public static class JmsBean implements MessageListener {
public void onMessage(Message message) {
}
}
The MDB container itself is not actually JMS-aware at all. It simply understands that it should hook the bean up to a specific Resource Adapter.
<openejb>
<Resource id="MyJmsResourceAdapter" type="ActiveMQResourceAdapter">
ServerUrl tcp://someHostName:61616
</Resource>
<Container id="MyJmsMdbContainer" ctype="MESSAGE">
ResourceAdapter MyJmsResourceAdapter
</Container>
</openejb>
The above shows an MDB Container hooked up to a Resource Adapter that uses JMS via ActiveMQ.
Here is an example that shows an MDB Container hooked up to a Quartz Resource Adapter
It isn't possible to tell the MDB Container about JMS specific things as per specification, the relationship is much more generic than that. This blog post gives some insight as to how things work.

Resources