[EJB3 Development] - jboss & NoInitialContextException
by mr f
mr f [https://community.jboss.org/people/mrf] created the discussion
"jboss & NoInitialContextException"
To view the discussion, visit: https://community.jboss.org/message/772380#772380
--------------------------------------------------------------
Hi,
I recently started learning EJB. I was trying to follow the work book examples from the EJB 3.0 book by Bill Burke & Richard Monson-Haefel. I have an eclipse, and JBoss 7 Final configured. I was able to deploy my first stateless bean and an entity to the server, but I am not able to run the client. The exception I get is:
javax.naming.NoInitialContextException: Cannot instantiate class: org.jnp.interfaces.NamingContextFactory [Root exception is java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory]
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.InitialContext.<init>(Unknown Source)
at com.titan.clients.Client.getInitialContext(Client.java:37)
at com.titan.clients.Client.main(Client.java:11)
Caused by: java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.naming.internal.VersionHelper12.loadClass(Unknown Source)
... 6 more
The client code:
package com.titan.clients;
import javax.naming.Context;
import com.titan.domain.Cabin;
import com.titan.travelagent.TravelAgentBeanRemote;
public class Client {
public static void main(String[] args) {
try {
Context jndiContext = getInitialContext();
Object ref = jndiContext.lookup("TravelAgentBean/remote");
TravelAgentBeanRemote dao = (TravelAgentBeanRemote) ref;
Cabin cabin_1 = new Cabin();
cabin_1.setId(1);
cabin_1.setName("Master Suite");
cabin_1.setDeckLevel(1);
cabin_1.setShipId(1);
cabin_1.setBedCount(3);
dao.createCabin(cabin_1);
Cabin cabin_2 = dao.findCabin(1);
System.out.println(cabin_2.getName());
System.out.println(cabin_2.getDeckLevel());
System.out.println(cabin_2.getShipId());
System.out.println(cabin_2.getBedCount());
} catch (javax.naming.NamingException ne) {
ne.printStackTrace();
}
}
public static Context getInitialContext()
throws javax.naming.NamingException {
return new javax.naming.InitialContext();
}
}
The jndi.properties file:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
I also tried setting the properties by injecting the constructor: new InitialContext(properties);
Sadly, to no avail...
The persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="titan">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
</persistence>
I'll be happy to post any more files/contents, am just not sure what else can be helpful or is needed.
There are tones of similar issues on the internet, but I wasn't able to fix my issue.
Can anyone help me to sort it out?
Thanks
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/772380#772380]
Start a new discussion in EJB3 Development at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&con...]
10 years, 7 months
[JBoss AS 7 Development] - WebApps sharing JPA entities in one cache
by Björn See
Björn See [https://community.jboss.org/people/Ernie2705] created the discussion
"WebApps sharing JPA entities in one cache"
To view the discussion, visit: https://community.jboss.org/message/772196#772196
--------------------------------------------------------------
Hi,
i´ve been playing around a while now with trying to deploy several (spring+jpa) web applications in one jboss 7 instance and getting them to share their entities in one infinispan cache.
Each web application ships some jars with it which contain several (maybe the same) POJO entity classes. Every app has its own persistence and application context.
I read and learned that in such an environment it is not possible to use one single cache instance. Infinispan creates an instance for each web application which makes the cache mechanism useless for my case.
Now I read about the possibility to use a standalone infinispan cache server and connect it to the JBoss instance as remote cache server. So I tried this configured the JBoss to use a remote-store, started infinispan server and JBoss server but the entities are not cached on the remote server. I also do not see anything from my entities in the jmx console of infinispan.
Here is my configuration:
{code:xml}
<subsystem xmlns="urn:jboss:domain:infinispan:1.2" default-cache-container="hibernate">
<cache-container name="hibernate" default-cache="entity" start="EAGER">
<local-cache name="entity" start="EAGER">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="1000000"/>
<expiration max-idle="100000"/>
<remote-store socket-timeout="60000">
<remote-server outbound-socket-binding="remote-store-hotrod-server"/>
</remote-store>
</local-cache>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="1000000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</local-cache>
</cache-container>
</subsystem>
...
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
...
<outbound-socket-binding name="remote-store-hotrod-server">
<remote-destination host="127.0.0.1" port="11222"/>
</outbound-socket-binding>
</socket-binding-group>
{code}
I´m feeling very uncertain with all this cause I did not find any working example for such a scenario. I even did not find an example or description of the configuration for using remote store, infinispan server and JPA.
Maybe someone could give me a hint or link to some documentation or could just tell me, that this is not the right way to solve the problem?!?
Thanks in advance,
Ernie
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/772196#772196]
Start a new discussion in JBoss AS 7 Development at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&con...]
10 years, 7 months
[JBoss AS 7 Development] - Re: jboss-modules: Module Repository SPI and Extensibility
by Andrew Rubinger
Andrew Rubinger [https://community.jboss.org/people/ALRubinger] created the discussion
"Re: jboss-modules: Module Repository SPI and Extensibility"
To view the discussion, visit: https://community.jboss.org/message/772248#772248
--------------------------------------------------------------
I've actually been giving this some thought, too, but left it out of this discussion for the time-being. Now that you raise it, what the hell. :)
If we were to build out a remote repository of modules (much like Maven Central), it'd open the door to on-demand installation of services into JBossAS. Carlo used to envision something like a "yum" or "apt-get" feature which could map a named service into a series of dependencies to be brought in and installed.
Additionally, we could perform upgrades of running services; it'd even be possible to have two versions of the same subsystem running concurrently in a single VM, provided we worked out a way to synchronize access to shared external resources (like ports). It'd be nice to have a user application A running on JBossWeb version X alongside user application B running on JBossWeb version Y; users wouldn't have to touch application A until they're ready. To some extent this is already possible by bundling frameworks inside the deployment.
The real value-add for me here is that we'd essentially be able to match what RHN (Red Hat Network) does for RHEL - provide a subscription service to push one-click upgrades to all servers in a Domain or ServerGroup.
One obvious hitch I see is the use of "main" as a default; I suspect that modules would have to become more explicit about the versions they depend upon. As it stands, JBossAS ships with a single module repository populated with the versions it needs - we'd have to expand this notion such that all modules would be aware that they could be housed in a much more expansive repository (which would grow over time) and be explicit about their versioned dependencies.
Has any of the above been discussed/planned in the context of JBossAS.next?
S,
ALR
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/772248#772248]
Start a new discussion in JBoss AS 7 Development at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&con...]
10 years, 7 months
[JBoss AS 7 Development] - Re: jboss-modules: Module Repository SPI and Extensibility
by Andrew Rubinger
Andrew Rubinger [https://community.jboss.org/people/ALRubinger] created the discussion
"Re: jboss-modules: Module Repository SPI and Extensibility"
To view the discussion, visit: https://community.jboss.org/message/772249#772249
--------------------------------------------------------------
And Randall, just to be complete, the RepositoryModuleLoader I've been playing with looks a bit like:
/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.modules;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
/**
* {@link ModuleLoader} implementation which loads from a local module repository. If no matching module is found
* locally, an attempt will be made to resolve module resources from a (possibly remote) repository accessible via a
* root {@link URL}.
*
* <br />
* <br />
*
* The default location of the local module repository is located on the filesystem at
* <code>$USER_HOME/.jboss/modules/repo</code>, unless overridden by explicitly-providing a location via
* {@link RepositoryModuleLoader#create(URL, File)}. New {@link RepositoryModuleLoader} instances with the default local
* repository may be created using {@link RepositoryModuleLoader#create(URL)}.
*
* @author <a href="mailto:alr@jboss.org">Andrew Lee Rubinger</a>
*/
public final class RepositoryModuleLoader extends ModuleLoader {
private static final Logger log = Logger.getLogger(RepositoryModuleLoader.class.getName());
private static final String DEFAULT_NAME_REPOSITORY = ".jboss" + File.separatorChar + "modules"
+ File.separatorChar + "repo";
private static final File USER_HOME_DIR = new File(SecurityActions.getSystemProperty("user.home"));
private static final File DEFAULT_LOCAL_REPO = new File(USER_HOME_DIR, DEFAULT_NAME_REPOSITORY);
private static final String NAME_MODULES_DESCRIPTOR = "module.xml";
private static final String ELEMENT_NAME_RESOURCE_ROOT = "resource-root";
private static final String ELEMENT_NAME_DEPENDENCIES = "dependencies";
private static final String ELEMENT_NAME_MODULE = "module";
private static final String ATTRIBUTE_NAME_PATH = "path";
private static final String ATTRIBUTE_NAME_NAME = "name";
private static final String SUFFIX_INDEX = ".index";
/**
* Root of the (possibly) remote repository from which to fetch modules
*/
private final URL rootUrl;
/**
* Root of the local module repository
*/
final File localRepoRoot;
/**
* Delegate used to load modules from the local module repository
*/
private final LocalModuleLoader localDelegate;
/**
* Creates a new instance using the specified root {@link URL} for the backing repository and the specified
* {@link File} root for the local repository. Both arguments are required, and the local repository root must both
* exist and be a directory, else {@link IllegalArgumentException} will be raised.
*
* @param rootUrl
* @param localRepoRoot
*/
private RepositoryModuleLoader(final URL rootUrl, final File localRepoRoot) throws IllegalArgumentException {
if (rootUrl == null) {
throw new IllegalArgumentException("Root URL must be specified");
}
if (localRepoRoot == null) {
throw new IllegalArgumentException("Local Repository Root must be specified");
}
if (!localRepoRoot.exists()) {
throw new IllegalArgumentException("Local Repository Root must exist: " + localRepoRoot);
}
if (!localRepoRoot.isDirectory()) {
throw new IllegalArgumentException("Local Repository Root must be a directory: " + localRepoRoot);
}
this.localRepoRoot = localRepoRoot;
this.rootUrl = rootUrl;
this.localDelegate = new LocalModuleLoader(new File[] { localRepoRoot.getAbsoluteFile() });
}
/**
* Creates a new {@link RepositoryModuleLoader} instance using the specified root URL from which to fetch modules
* and the specified local repository root to cache downloaded modules.
*
* @param rootUrl
* @param localRepoRoot
* @return
* @throws IllegalArgumentException
* If either argument is not specified, or if the local repository root does not exist or is not a
* directory
*/
public static RepositoryModuleLoader create(final URL rootUrl, final File localRepoRoot)
throws IllegalArgumentException {
return new RepositoryModuleLoader(rootUrl, localRepoRoot);
}
/**
* Creates a new {@link RepositoryModuleLoader} instance using the specified root URL from which to fetch modules
* and the default local repository root (USER_HOME_DIR/.jboss/modules/repo) to cache downloaded modules.
*
* @param rootUrl
* @return
* @throws IllegalArgumentException
* If the root {@link URL} is not specified
*/
public static RepositoryModuleLoader create(final URL rootUrl) throws IllegalArgumentException {
// Create default local repo if it doesn't exist
if (!DEFAULT_LOCAL_REPO.exists() && !DEFAULT_LOCAL_REPO.mkdirs()) {
throw new RuntimeException("Could not create default local repository: "
+ DEFAULT_LOCAL_REPO.getAbsolutePath());
}
return new RepositoryModuleLoader(rootUrl, DEFAULT_LOCAL_REPO);
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#toString()
*/
@Override
public String toString() {
return RepositoryModuleLoader.class.getSimpleName() + " with root URL: " + this.rootUrl
+ " and using local module repository root " + localRepoRoot.getAbsolutePath();
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#preloadModule(org.jboss.modules.ModuleIdentifier)
*/
@Override
protected Module preloadModule(final ModuleIdentifier identifier) throws ModuleLoadException {
Module module;
try {
module = ModuleLoader.preloadModule(identifier, localDelegate);
} catch (final ModuleNotFoundException mnfe) {
// Fetch and try again
this.fetchModuleAssets(identifier);
module = ModuleLoader.preloadModule(identifier, localDelegate);
}
// Return
return module;
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#findModule(org.jboss.modules.ModuleIdentifier)
*/
@Override
protected ModuleSpec findModule(final ModuleIdentifier moduleIdentifier) throws ModuleLoadException {
// We never load the module, the local delegate does via preloadModule
// FIXME This mechanism really breaks the stated purpose of the SPI, raise the issue to DML
throw new UnsupportedOperationException("Should never be reached, we use a delegate loader");
}
/**
* Obtains all module resources for the given (required) {@link ModuleIdentifier}. Will recurse to obtain dependent
* module assets as well.
*
* @param moduleIdentifier
*/
private void fetchModuleAssets(final ModuleIdentifier moduleIdentifier) {
assert moduleIdentifier != null : "Module identifier is required";
// Fetch the module.xml into the local modules repo
final String relativePath = toHttpPathString(moduleIdentifier);
final File localRepoModuleRoot = new File(localRepoRoot, toLocalDiskPathString(moduleIdentifier));
final File localModulesFile;
try {
localModulesFile = this.downloadToLocalRepository(relativePath, NAME_MODULES_DESCRIPTOR,
localRepoModuleRoot);
} catch (final FileNotFoundException fnfe) {
throw new RuntimeException("Could not find " + NAME_MODULES_DESCRIPTOR, fnfe);
}
// Parse out the name of the resource root and any dependencies
String resourceRootPath = null;
final Set<String> dependencies = new HashSet<String>();
final XMLStreamReader reader;
try {
reader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(localModulesFile));
} catch (final FileNotFoundException fnfe) {
throw new RuntimeException("Could not find the file we've just written: "
+ localModulesFile.getAbsolutePath());
} catch (final XMLStreamException xmlse) {
throw new RuntimeException(xmlse);
} catch (final FactoryConfigurationError fce) {
throw new RuntimeException(fce);
}
try {
boolean inDependenciesSection = false;
readerLoop: while (reader.hasNext()) {
final int next = reader.next();
switch (next) {
case XMLStreamReader.START_ELEMENT:
String elementName = reader.getLocalName();
if (ELEMENT_NAME_RESOURCE_ROOT.equals(elementName)) {
final int numAttributes = reader.getAttributeCount();
for (int i = 0; i < numAttributes; i++) {
final String attribute = reader.getAttributeLocalName(i);
if (ATTRIBUTE_NAME_PATH.equals(attribute)) {
resourceRootPath = reader.getAttributeValue(i);
}
}
continue;
}
if (ELEMENT_NAME_DEPENDENCIES.equals(elementName)) {
inDependenciesSection = true;
continue;
}
if (ELEMENT_NAME_MODULE.equals(elementName) && inDependenciesSection) {
final int numAttributes = reader.getAttributeCount();
for (int i = 0; i < numAttributes; i++) {
final String attribute = reader.getAttributeLocalName(i);
if (ATTRIBUTE_NAME_NAME.equals(attribute)) {
dependencies.add(reader.getAttributeValue(i));
}
}
}
continue;
case XMLStreamReader.END_ELEMENT:
elementName = reader.getLocalName();
if (ELEMENT_NAME_DEPENDENCIES.equals(elementName)) {
break readerLoop;
}
}
}
} catch (final XMLStreamException xmlse) {
throw new RuntimeException("Encountered error reading from " + localModulesFile.getAbsolutePath(), xmlse);
}
if (resourceRootPath == null) {
// Could be to system path, so we're done here
return;
}
// Get all dependencies recursively
for (final String dependency : dependencies) {
final ModuleIdentifier moduleId = ModuleIdentifier.fromString(dependency);
this.fetchModuleAssets(moduleId);
}
// Download the resource root
try {
this.downloadToLocalRepository(relativePath, resourceRootPath, localRepoModuleRoot);
} catch (final FileNotFoundException fnfe) {
throw new RuntimeException("Specified resource root could not be found: " + resourceRootPath);
}
// Download the index file
final String indexFileName = resourceRootPath + SUFFIX_INDEX;
try {
this.downloadToLocalRepository(relativePath, indexFileName, localRepoModuleRoot);
} catch (final FileNotFoundException fnfe) {
// Ignore, must be no index
if (log.isLoggable(Level.FINEST)) {
log.finest("No index file found: " + indexFileName + "; skipping.");
}
}
}
/**
* Performs the download of the remote file name located in the relative remote path to the specified parent
* directory. All arguments are required.
*
* @param relativeRemotePath
* @param remoteFileName
* @param parentDir
* @return
* @throws FileNotFoundException
* If the requested resource could not be found in the remote path with the remote file name
*/
private File downloadToLocalRepository(final String relativeRemotePath, final String remoteFileName,
final File parentDir) throws FileNotFoundException {
assert relativeRemotePath != null;
assert remoteFileName != null;
assert parentDir != null;
final URL relativePathURL;
final URL fullURL;
try {
relativePathURL = new URL(rootUrl, relativeRemotePath);
fullURL = new URL(relativePathURL, remoteFileName);
} catch (final MalformedURLException murle) {
throw new RuntimeException(murle);
}
final File targetFile = new File(parentDir, remoteFileName);
final InputStream in;
try {
if (log.isLoggable(Level.INFO)) {
log.info("Writing: " + fullURL + " as " + targetFile);
}
in = fullURL.openStream();
} catch (final IOException ioe) {
throw new RuntimeException("Could not get stream to " + fullURL.toExternalForm(), ioe);
}
if (in == null) {
throw new FileNotFoundException("Could not find requested file at URL: " + fullURL.toExternalForm());
}
if (!parentDir.exists() && !parentDir.mkdirs()) {
throw new IllegalStateException("Could not create parent directory: " + parentDir);
}
OutputStream out = null;
try {
try {
out = new FileOutputStream(targetFile);
} catch (final FileNotFoundException fnfe) {
throw new RuntimeException(fnfe);
}
final byte[] buffer = new byte[512]; // Relatively smaller buffer as we don't know how far away the
// source is
try {
int readBytes = 0;
while ((readBytes = in.read(buffer)) != -1) {
out.write(buffer, 0, readBytes);
if (log.isLoggable(Level.INFO)) {
// Only way to show incremental progress without flooding the log with unnecessary lines is to
// write straight to console
System.out.print('.');
}
}
if (log.isLoggable(Level.INFO)) {
System.out.println();
}
} catch (final IOException ioe) {
throw new RuntimeException(ioe);
}
} finally {
try {
if (out != null) {
out.close();
if (log.isLoggable(Level.INFO)) {
log.info("Wrote " + targetFile.getAbsolutePath());
}
}
} catch (final IOException ioe) {
// Swallow
}
}
// Return
return targetFile;
}
private static String toHttpPathString(final ModuleIdentifier moduleIdentifier) {
return toPathString(moduleIdentifier, '/');
}
private static String toLocalDiskPathString(final ModuleIdentifier moduleIdentifier) {
return toPathString(moduleIdentifier, File.separatorChar);
}
private static String toPathString(final ModuleIdentifier moduleIdentifier, final char replacementChar) {
final StringBuilder builder = new StringBuilder(40);
builder.append(moduleIdentifier.getName().replace('.', replacementChar));
builder.append(replacementChar).append(moduleIdentifier.getSlot());
builder.append(replacementChar);
return builder.toString();
}
}
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/772249#772249]
Start a new discussion in JBoss AS 7 Development at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&con...]
10 years, 7 months
[JBoss AS 7 Development] - jboss-modules: Module Repository SPI and Extensibility
by Andrew Rubinger
Andrew Rubinger [https://community.jboss.org/people/ALRubinger] created the discussion
"jboss-modules: Module Repository SPI and Extensibility"
To view the discussion, visit: https://community.jboss.org/message/772203#772203
--------------------------------------------------------------
I have the following use cases I'd like to fulfill:
1) Boot JBossAS from a single-JAR distribution
2) Boot JBossAS from a slim executable JAR, using module libraries located on a remote repository (if not already in a user's local module repository)
3) Create a modular Arquillian Server Daemon executable JAR, with module root located inside of this JAR under META-INF/modules
>From my prototyping, all of these are possible using jboss-modules, though the SPI is a bit restrictive when it comes to abstracting out the module repository. With some improvements to the jboss-modules SPI, we could promote better extensibility. In particular, I'm finding ModuleLoader difficult to work with.
Reasoning:
protected abstract ModuleSpec findModule(final ModuleIdentifier moduleIdentifier) throws ModuleLoadException;
Fulfilling this contract is required of ModuleLoader subtypes. Typically this amounts to finding and parsing a "module.xml" file from the given ModuleIdentifier, but the mechanism for doing this (ModuleXmlParser) is package-private. It's therefore not very intuitive (or possible) for users outside of jboss-modules to meet the demands of the method signature.
David points out that ModuleLoader implementations are instead encouraged to use a delagation mechanism, via something like:
@Override
protected Module preloadModule(final ModuleIdentifier identifier) throws ModuleLoadException {
return ModuleLoader.preloadModule(identifier, this.delegate);
}
The issue here is that we need a delegate capable of servicing the request. LocalModuleLoader is fine for filesystem-based repositories (though it's final and cannot be extended), but modules could conceivably be located anywhere (and may even have some descriptor format other than module.xml). This is exacerbated by the unavailability of other ModuleLoader implementations which are not visible outside jboss-modules:
ClassPathModuleLoader
JarModuleLoader
For for my use cases 1) and 3) above, I believe my only options are to resort to a bit of a hack which unpacks the module root in a JAR to something that can be read by LocalModuleLoader. I'll paste that code below the fold[1].
Use case 2) I hope to see more discussion on; I have a patch in https://issues.jboss.org/browse/MODULES-146: https://issues.jboss.org/browse/MODULES-146: https://github.com/jbossas/jboss-modules/pull/22 https://github.com/jbossas/jboss-modules/pull/22.
Because we probably don't want to be changing the existing SPI much, perhaps introducing a new ModuleRepository SPI layer would make sense looking forward? David has mentioned an "install" SPI, but I think "installation" is still an implementation detail with respect to module loading. I believe an abstraction between jboss-modules and any backing module repository (which is a VFS) will do.
S,
ALR
PS - I could even make a ShrinkWrap-based ModuleRepository. :)
[1]
/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.arquillian.daemon.main;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Enumeration;
import java.util.UUID;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.jboss.modules.LocalModuleLoader;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
import org.jboss.modules.ModuleLoader;
import org.jboss.modules.ModuleSpec;
/**
* Hack implmentation of a {@link ModuleLoader} capable of loading modules contained in a JAR under a known module root.
* Explodes the module root into a temporary directory on the filesystem, by which a delegate {@link LocalModuleLoader}
* may then load the modules. Temporarily necessary due to API restrictions in jboss-modules whereby the JarModuleLoader
* is not accessible, nor is parsing a {@link ModuleSpec} from a <code>module.xml</code> file.
*
* @author <a href="mailto:alr@jboss.org">Andrew Lee Rubinger</a>
* @deprecated In place until we can work out proper support for this either in jboss-modules or via a new jboss-modules
* API which lets us load from a JAR
*/
@Deprecated
final class HackJarModuleLoader extends ModuleLoader {
private static final String SYSPROP_NAME_TMP_DIR = "java.io.tmpdir";
private static final String PREFIX_MODULES_DIR = "modules-";
/**
* Local delegate for loading modules once unpacked
*/
private final ModuleLoader delegate;
/**
* Target location the modules will be unpacked to
*/
private final File localModulesLocation;
/**
* Creates a new {@link ModuleLoader} instance for the specified JAR file, where modules are located in a root
* denoted by the specified <code>moduleRoot</code> parameter (which is relative to the root of the JAR).
*
* @param jar
* @param moduleRoot
* @throws IllegalArgumentException
* If either argument is not specified
*/
public HackJarModuleLoader(final JarFile jar, final String moduleRoot) throws IllegalArgumentException {
// Precondition checks
if (jar == null) {
throw new IllegalArgumentException("JAR file must be specified");
}
if (moduleRoot == null || moduleRoot.length() == 0) {
throw new IllegalArgumentException("Module root within the JAR must be specified");
}
// Set up the local temp modules directory
final String tempDirName = SecurityActions.getSystemProperty(SYSPROP_NAME_TMP_DIR);
final File tempDir = new File(tempDirName);
final File modulesDir = new File(tempDir, PREFIX_MODULES_DIR + UUID.randomUUID().toString());
if (!modulesDir.mkdir()) {
throw new IllegalStateException("Could not create modules directory: " + modulesDir.getAbsolutePath());
}
// Explode
final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
if (entry.isDirectory()) {
continue;
}
final String name = entry.getName();
if (name.startsWith(moduleRoot)) {
final String parsedFullFileName = name.substring(moduleRoot.length() + 1);
final int lastDirIndex = parsedFullFileName.lastIndexOf('/');
if (lastDirIndex > 0) {
final String targetRelativeDirName = parsedFullFileName.substring(0, lastDirIndex);
final File targetDir = new File(modulesDir, targetRelativeDirName);
if (!targetDir.exists()) {
final boolean created = targetDir.mkdirs();
if (!created) {
throw new IllegalStateException("Could not create target directory: " + targetDir);
}
}
final String fileName = parsedFullFileName.substring(lastDirIndex);
final File targetFile = new File(targetDir, fileName);
registerRecursiveDeleteOnExit(targetFile, modulesDir);
InputStream in = null;
OutputStream out = null;
try {
in = jar.getInputStream(entry);
out = new FileOutputStream(targetFile);
final byte[] buffer = new byte[4096];
int read = 0;
while ((read = in.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, read);
}
} catch (final IOException e) {
throw new RuntimeException("Could not write " + entry.getName() + " to "
+ targetFile.getAbsolutePath(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (final IOException ioe) {
// Swallow
}
}
if (out != null) {
try {
out.close();
} catch (final IOException ioe) {
// Swallow
}
}
}
}
}
}
// Set
this.delegate = new LocalModuleLoader(new File[] { modulesDir });
this.localModulesLocation = modulesDir;
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#preloadModule(org.jboss.modules.ModuleIdentifier)
*/
@Override
protected Module preloadModule(final ModuleIdentifier identifier) throws ModuleLoadException {
assert identifier != null;
return ModuleLoader.preloadModule(identifier, delegate);
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#toString()
*/
@Override
public String toString() {
return HackJarModuleLoader.class.getSimpleName() + " delegating to modules in "
+ localModulesLocation.getAbsolutePath();
}
/**
* {@inheritDoc}
*
* @see org.jboss.modules.ModuleLoader#findModule(org.jboss.modules.ModuleIdentifier)
*/
@Override
protected ModuleSpec findModule(final ModuleIdentifier moduleIdentifier) throws ModuleLoadException {
// Due to incompatible API
throw new UnsupportedOperationException("All loading should be done via the delegate in preoadModule");
}
private static void registerRecursiveDeleteOnExit(final File child, final File root) {
if (System.getSecurityManager() == null) {
child.deleteOnExit();
} else {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
child.deleteOnExit();
return null;
}
});
}
final File parent = child.getParentFile();
if (!child.equals(root)) {
registerRecursiveDeleteOnExit(parent, root);
}
}
}
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/772203#772203]
Start a new discussion in JBoss AS 7 Development at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&con...]
10 years, 7 months