[
https://issues.jboss.org/browse/JBTM-2189?page=com.atlassian.jira.plugin....
]
Tom Jenkinson commented on JBTM-2189:
-------------------------------------
Hi Chris,
Many thanks for your interest in Narayana. Normally for something like this it is best to
start with a discussion on our forums over here:
https://community.jboss.org/en/jbosstm.
That said, please can you add a little more detail into the description as to the nature
of the bug. We do already function in Java SE and also complex classloader hierarchies so
this may be a corner case which we would be happy to work with you to address. I am not
familiar with OneJar, is it a maven plugin that will put all the dependency jar classes
into the same Jar as the application jar? The main problem with your report as it stands
is that we don't have a well defined reason for _why_ the change needs to be made, if
you can express the motivation for the change in more general terms then we can get it
merged. As you say, the fix looks like it should work in our currently supported options
so it shouldn't be a problem to get it merged once we have more context to backup the
need to merge it.
Once we understand the problem better, and we proceed with your approach, please can you:
1. Sign the CLA over here:
https://cla.jboss.org/ (project is JBoss Transactions)
2. Fork:
https://github.com/jbosstm/narayana
3. Raise a pull request on the main repo with your fix in. It should be easier to review
inline, plus it will get CI run on it.
Many thanks for the contribution!
Tom
Bootstrapping from Complex Classloader (OneJar)
-----------------------------------------------
Key: JBTM-2189
URL:
https://issues.jboss.org/browse/JBTM-2189
Project: JBoss Transaction Manager
Issue Type: Feature Request
Security Level: Public(Everyone can see)
Components: Common
Affects Versions: 5.0.1
Environment: JDK 8, OneJar 0.97
Reporter: Chris Pheby
Assignee: Tom Jenkinson
I am using Narayana within a JavaSE application. The application is compiled into a
single Jar. When executing, Narayana fails to bootstrap properly.
The first problem is within com.arjuna.common.util.ConfigurationInfo.
Lines 111-115 aim to load the MANIFEST file from the classpath:
String pathToManifest = basePath+"/META-INF/MANIFEST.MF";
InputStream is = null;
try {
is = new URL(pathToManifest).openStream();
I replaced this with:
InputStream is = null;
// BEGIN - WORKAROUND FOR ONE-JAR
try {
String targetPrefix = pathToThisClass.substring(0, pathToThisClass.length() -
"/com/arjuna/common/util/ConfigurationInfo.class".length());
Enumeration<URL> resources =
ConfigurationInfo.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
URL next = resources.nextElement();
if (next.toString().startsWith(targetPrefix)) {
is = next.openStream();
break;
}
}
// END - WORKAROUND FOR ONE-JAR
This should work for all environments.
Changes are also required in
com.arjuna.common.util.propertyservice.AbstractPropertiesFactory to attempt loading from
classpath as well as file system:
The last line of initDefaultProperties (195) needed changing to:
defaultProperties = getPropertiesFromClasspath(propertyFileName,
PropertiesFactoryStax.class.getClassLoader());
if (defaultProperties == null) {
defaultProperties = getPropertiesFromFile(propertyFileName,
PropertiesFactoryStax.class.getClassLoader());
}
}
and the following methods added / replaced:
/**
* Returns the config properties read from a specified relative location on the
classpath.
*
* @param propertyFileName the file name relative to the classpath root.
* @return the Properties loaded from the specified source.
*/
public Properties getPropertiesFromClasspath(String propertyFileName, ClassLoader
classLoader) {
Properties properties = null;
try {
Enumeration<URL> resources =
ConfigurationInfo.class.getClassLoader().getResources(propertyFileName);
while (resources.hasMoreElements()) {
URL next = resources.nextElement();
properties = loadFromStream(next.openStream());
return properties;
}
} catch(Exception e) {
return null;
}
return properties;
}
/**
* Returns the config properties read from a specified location.
*
* @param propertyFileName the file name. If relative, this is located using the
FileLocator algorithm.
* @return the Properties loaded from the specified source.
*/
public Properties getPropertiesFromFile(String propertyFileName, ClassLoader
classLoader) {
String propertiesSourceUri = null;
try
{
// This is the point where the search path is applied - user.dir (pwd),
user.home, java.home, classpath
propertiesSourceUri =
com.arjuna.common.util.propertyservice.FileLocator.locateFile(propertyFileName,
classLoader);
}
catch(FileNotFoundException fileNotFoundException)
{
// try falling back to a default file built into the .jar
// Note the default- prefix on the name, to avoid finding it from the .jar at
the previous stage
// in cases where the .jar comes before the etc dir on the classpath.
URL url =
AbstractPropertiesFactory.class.getResource("/default-"+propertyFileName);
if(url == null) {
throw new RuntimeException("missing property file
"+propertyFileName);
} else {
propertiesSourceUri = url.toString();
}
}
catch (IOException e)
{
throw new RuntimeException("invalid property file
"+propertiesSourceUri, e);
}
Properties properties = null;
try {
properties = loadFromFile(propertiesSourceUri);
properties = applySystemProperties(properties);
} catch(Exception e) {
throw new RuntimeException("unable to load properties from
"+propertiesSourceUri, e);
}
return properties;
}
private Properties loadFromStream(InputStream inputStream) throws IOException {
Properties inputProperties = new Properties();
Properties outputProperties = new Properties();
try {
loadFromXML(inputProperties,inputStream);
} finally {
inputStream.close();
}
Enumeration namesEnumeration = inputProperties.propertyNames();
while(namesEnumeration.hasMoreElements()) {
String propertyName = (String)namesEnumeration.nextElement();
String propertyValue = inputProperties.getProperty(propertyName);
propertyValue = propertyValue.trim();
// perform JBossAS style property substitutions. JBTM-369
propertyValue = StringPropertyReplacer.replaceProperties(propertyValue);
outputProperties.setProperty(propertyName, propertyValue);
}
return outputProperties;
}
--
This message was sent by Atlassian JIRA
(v6.2.6#6264)