Implicity usage of Java Custom class loaders? - classloader

I've written some customer class loader that load some classes from a certain directory (that is not in the classpath), say:
class FileSystemClassLoader extends Classloader{
// implementation details
}
I have some directory say /home/mhewedy/classes/ that is not in the classpath, this directory contains some classes that I use the previous classlaoder to load.
how to use this classloader from the my code to load classes "simplicity" without writing : such code:
Thread.currentThread().setContextClassLoader(new FileSystemClassLoader());
// some code here ...
ClassLoader contextCL = Thread.currentThread().getcontextClassLoader();

Update to respond to OP edits:
When the JVM loads a class, it will use the classloader that loaded the "current" class (per JVM spec). So if you're in method Foo.main(), which was loaded with your custom classloader, and you want to create an instance of Bar, also loaded via that classloader, you don't have to do anything special.
However, if your current method is Baz.main(), and it was loaded via the system classpath (specified with -cp on the command line), then you have to explicitly load that class via the classloader. There's no way around this. The "context classloader" is meant for application code, to load resources; the JVM ignores it.
In almost all cases, you're better off constructing a classpath that includes your special classes.

Related

How can I prevent war libraries slf4j to collide with my project slf4j?

I am trying to deploy the reddog rdap-server war file into an embedded Jetty in my project. But everytime I am getting this eror:
java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
Problem is, the war file already contains slf4j. Any suggestions?
I tried to change my maven pom to "provider, which didn't help.
Use WebAppContext's (which it seems like from your error, and the mention of WebAppClassLoader).
Don't modify the Server or System classes lists on the WebAppContext or the WebAppClassLoader.
Don't set the WebAppContext.setParentLoaderPriority(boolean) field.
That's it.
Now you have the ClassLoader Isolation you are looking for.

EnableNeo4jRepositories.sessionFactoryRef is ignored / does nothing

I'm trying to configure a Spring Boot 1.5.9 project with multiple data sources, of which some are Neo4j.
The version of spring-data-neo4j I'm using is 4.2.9.
My goal is to use a different SessionFactory for different repositories, using a different Configuration class for each.
I've got this all working with Mongo but it seems that, even though the sessionFactoryRef is available on #EnableNeo4jRepositories, it simple does not get acted upon.
Abbreviated version of my configuration, with the general concepts:
#org.springframework.context.annotation.Configuration
#EnableNeo4jRepositories(basePackages = "<repo-package-name>", sessionFactoryRef = NEO4J_SESSIONFACTORY_NAME)
public class MyConfiguration {
protected static final String NEO4J_SESSIONFACTORY_NAME = "mySessionFactory";
#Bean(NEO4J_SESSIONFACTORY_NAME)
public SessionFactory mySessionFactory() {
SessionFactory sessionFactory = ...
// passing entity package corresponding to repository
return sessionFactory;
}
As mentioned, this construct works fine with spring-data-mongodb, however in neo4j it first starts out with an error:
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'getSessionFactory' that could not be found.
Action:
Consider defining a bean named 'getSessionFactory' in your configuration.
Turning on debug in the logger and a look through the code led me to SessionBeanDefinitionRegistrarPostProcessor, that contains the following code to get the sessionFactory:
private static String getSessionFactoryBeanRef(ConfigurableListableBeanFactory beanFactory) {
return beanFactory.containsBeanDefinition("sessionFactory") ? "sessionFactory" : "getSessionFactory";
}
Hmmm... hardcoded names for a bean, no sign of customisability.
I then proceeded to name my bean twice, #Bean("sessionFactory", NEO4J_SESSIONFACTORY_NAME), so the above code would pass.
The application started, but the problem is that the repositories get wired with whatever bean is called sessionFactory, effectively not using the sessionFactoryRef on the annotation.
To test this, I changed the name on the annotation to a non-existing bean and it continued to start (if I do this with the mongo-annotation, the application quits because the bean mentioned in mongoTemplateRef isn't available).
I dug a little deeper and found that, for mongo, it retrieves the bean reference in this class. The equivalent neo4j implementation has no such thing. It could of course be an implementation detail but I wasn't able to find any reference to the sessionFactoryRef attribute other than the annotation and the xml-schema.
There are also other places in the config classes that expect only one SessionFactory to be available.
So, in short, it seems to me that EnableNeo4jRepositories.sessionFactoryRef has no implementation and therefore simple doesn't do anything.
As a result, with the current code a single bean "sessionFactory" must be present and all repositories will be wired with this bean, regardless of the value of sessionFactoryRef.
Anybody else with a similar experience or any idea how to file a bug for this?

Weblogic 11 G : Altering default class loading

I have one query regarding Weblogic server 11 G class loading infrastructure.
Lets say I have two application jars named A.jar and B.jar loaded in classpath during server start up.
Both jar contains class say LoadMe.class and sever loads LoadMe.class from jar A.jar by default.
Now I want to alter above default behavior and want to load that class from B.jar instead of A.jar.
How can I do that?
Any help will be appreciated.
Whenever you use LoadMe class for the first time the ClassLoader will try to resolve the dependency using the CLASSPATH.
Now if you have to load the class from B.jar, then you will have to explicitly place path to that jar first and A.jar second in the CLASSPATH. So the ClassLoader will pick the class from B.jar first.
Try this link for more on ClassLoaders
Read this and change the classpath and the problem should be solved
Setting classpath in WebLogic 11G
UPDATE:
System.out.println("Classpath dependency for LoadClass: ");
URLClassLoader classLoader = (URLClassLoader)LoadMe.class.getClassLoader();
System.out.println(Arrays.toString(classLoader.getURLs()));
System.out.println("Classpath dependency for Context: ");
URLClassLoader classLoader1 = (URLClassLoader)Thread.currentThread().getContextClassLoader());
System.out.println(Arrays.toString(classLoader.getURLs()));

Best way to initialize JpaPersistModule

I use com.google.inject.persist.jpa.JpaPersistModule in my application. The configuration is located in persistence.xml file, but some of the properties are dynamic and I don't want store them in this file (for example javax.persistence.jdbc.url etc) but rather inject them from some other source.
I know that there's a JpaPersistModule.properties(java.util.Properties p) method that allows to do exactly what I need. The problem is that I don't see a good way to pass that java.util.Properties object to the module. I don't want to explicitely create an instance of java.util.Properties in the module code, but would rather use some guice-style mechanism to inject it.
Is that possible at all? How would you decouple JPA module and its configuration properties?
Modules are generally created manually, because they're created before the Injector is. You can jump through some hoops to inject a module if you really want, such as creating one injector, using it to create one or more modules, and then creating a child injector using those. I don't really see the point though. Creating the Properties manually and passing them in doesn't seem like a big deal to me.
Try this
public class DbModule extends AbstractModule {
private final Properties properties;
public DbModule(Properties properties) {
this.properties = properties;
}
#Override
protected void configure() {
JpaPersistModule jpa = new JpaPersistModule("my-unit");
jpa.properties(properties);
jpa.configure(binder());
//bind other stuff here...
}
}

fake directories for .net unit testing

I'm trying to create a unit test for a code similar to this:
foreach (string domainName in Directory.GetDirectories(server.Path))
{
HandleDomainDirectory(session, server, domainName);
}
The problem is that I'm using the System.IO.Directory class in my code.
How can I create a testing method that won't be dependent on any folder I have on my hard disk.
In other words, How can I fake the response of "Directory.GetDirectories(server.Path)"?
(Please note, I do control the "server" object in my class, therefore i can give any path i want)
Thanks.
Rather than calling Directory.GetDirectories(server.Path) directly, you could create an interface like IDirectoryResolver with a single method that takes a path string and returns the list of directories. The class containing your code above would then need a property or field of type IDirectoryResolver, which can be injected through the constructor or a setter.
For your production code, you would then create a new class that implements the IDirectoryResolver interface. This class could use the Directory.GetDirectories method in its implementation of the interface method.
For unit testing, you could create a MockDirectoryResolver class which implements IDirectoryResolver (or use a mocking library to create a mock instance for the interface). The mock implementation can do whatever you need it to do.
You would inject a wrapper class.
public class DirectoryFetcher
{
public virtual List<string> GetDirectoriesIn(string directory)
{
return Directory.GetDirectories(directory);
}
}
And then inject that:
foreach(string directory in _directoryFetcher.GetDirectoriesIn(server.Path))
{
// Whatever
}
You can then Mock that guy at the injection point (this example uses Moq, and constructor injection):
Mock<DirectoryFetcher> mockFetcher = new Mock<DirectoryFetcher>();
mockFetcher.Setup(x => x.GetDirectoriesIn("SomeDirectory")).Returns(new List<string>
{
"SampleDirectory1",
"SampleDirectory2"
});
MyObjectToTest testObj = new MyObjectToTest(mockFetcher.Object);
// Do Test
When communicating with the outside world, such as file system, databases, web services etc. , you should always consider using wrapper classes like the others before me suggested. Testability is one major argument, but an even bigger one is: The out side world changes, and you have no control over it. Folders move, user rights changes, new disk drives appears and old ones are removed. You only want to care about stuff like that in one place. Hence, the wrapper -- let's call it DirectoryResolver like Andy White suggested ealier.
So, wrap your file system calls, extract an interface, and inject that interface where you need to communicate with the file system.
The best solution I've found was to use Moles. The code is very specific, and must do very specific thing. Wrapping it with wrapper class will be redundant. The only reason I needed wrapper class is in order to write tests. Moles allows me to write the tests without any wrapper class :)