OSGI & Apache Commons-DBCP Classloading Issue - postgresql

I inherited some code that is using the Apache commons-dbcp Connection pools in an OSGi bundle. This code works fine with Eclipse/Equinox OSGi version 3.4.3 (R34x_v20081215), commons-dbcp 1.2.2 and the postgres jdbc3 8.3.603 bundles from springsource.org.
I wanted to modernize, maybe this was my first mistake!
When I use the new version of Felix or Equinox OSGI Cores with the new postgresql JDBC3 or JDBC4 bundles along with the latest version of commons-dbcp (1.4.1), I am getting a classloading issue. I have done numerous searches and found that the commons-dbcp code should have a fix DBCP-214, but it still seems to fail.
I have tried to put the org.postgresql on the commons-dbcp MANIFEST.MF import-package line, but that did not work either.
I wrote a simple test in an activator that first does a basic class.forName() and DriverManager.getConnection(), this works fine, but when I add in BasicDataSource() and setup the connection with BasicDataSource.getConnection(), I get the ClassNotFoundException. See the code example below.
Thanks in Advance for any help, suggestions, ...
Sau!
// This one fails with an exception
public void dsTest() {
BasicDataSource bds = new BasicDataSource();
ClassLoader cl;
try {
logger.debug("ContextClassLoader: {}",
Thread.currentThread().getContextClassLoader().toString());
cl = this.getClass().getClassLoader();
logger.debug("ClassLoader: {}", cl);
if (bds.getDriverClassLoader() != null) {
logger.debug(bds.getDriverClassLoader().toString());
}
// The failure is the same with and with the setDriverClassLoader() line
bds.setDriverClassLoader(cl);
bds.setDriverClassName("org.postgresql.Driver");
bds.setUrl("jdbc:postgresql://127.0.0.1/dbname");
bds.setUsername("user");
bds.setPassword("pword");
Class.forName("org.postgresql.Driver").newInstance();
conn = bds.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM table");
conn.close();
logger.debug("Closed DataSource Test");
} catch (Exception ex) {
ex.printStackTrace();
logger.debug("Exception: {} ", ex.getMessage());
}
}
// This one works
public void managerTest() {
ClassLoader cl;
try {
cl = this.getClass().getClassLoader();
logger.debug("ClassLoader: {}", cl);
Class.forName("org.postgresql.Driver").newInstance();
String url = "jdbc:postgresql://127.0.0.1/dbname";
conn = DriverManager.getConnection(url, "user", "pword");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM table");
conn.close();
logger.debug("Closed Manger Test");
} catch (Exception ex) {
ex.printStackTrace();
logger.debug("Exception: {} ", ex.getMessage());
}
}

this is due to the fact that the commons-dbcp bundle cannot look at the actual driver class, because of the osgi class loader. The solution to this is to attach a fragment to the commons-dbcp class with Dynamic Import *. The actual headers that you need in your MANIFEST are the following:
Fragment-Host: org.apache.commons.dbcp
DynamicImport-Package: *
After this, the code you mentioned worked. Hope this doesnt come too late.

Related

ClassNotFoundException jdbc driver postgresql [duplicate]

This question already has an answer here:
ClassNotFoundException with PostgreSQL and JDBC
(1 answer)
Closed 5 years ago.
so I am writing a programm that accesses a database but whenever i can the method Class.forName("org.postgresql.Driver); the ClassNotFoundException is thrown.
I have looked at every solution to this problem I could find, but nothing worked.
I hope you can help me with this.
Code:
public static void editDatabase(String[] values){
Connection connect = null;
Statement statement = null;
ResultSet result = null;
try {
Class.forName("org.postgresql.Driver");
connect = DriverManager.getConnection(values[0],values[1],values[2]);
statement = connect.createStatement();
result = statement.executeQuery("select * from Kunde");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This problem means that your project does not load 'org.postgresql.Driver' at init.
If you are using IntelliJ, you must add org.postgresql.Driver using 'Project Structure', it's located at your top right window.
If you're not using IDE, I do recommend you to use one.
You could also use Maven and add 'org.postgresql.Driver' as a requirement for your project.
Bye.

Wicket configuration for nashorn

I recently upgraded my java version from java 1.7 to java 1.8. After the upgrade i am getting this error.
Caused by: ECMAScript Exception: Type Error: Can not find a common class loader for ScriptObject and My Interface.
Which version of wicket do i need to use which supports java 1.8 and nashorn script engine. Also do i need to configure anything related to Script Engine for wicket.
I have tried adding this dependency
<dependency>
<groupId>org.wicketstuff</groupId>
<artifactId>wicketstuff-nashorn</artifactId>
<version>7.4.0</version>
</dependency>
and ScriptEngineManager sem = new ScriptEngineManager();
engine = sem.getEngineByName("nashorn");
but i am still getting the same issue.
Please help me fix this issue.
Below is my method
private final ScriptEngine engine;
ScriptEngineManager sem = new ScriptEngineManager();
engine = sem.getEngineByName("nashorn");
public <K> K getNewInterface(MyScript myScript){
ScriptContext ctx = new SimpleScriptContext();
String script = myScript.getScript();
if(Strings.isEmpty(script)) {markInvalid(myScript, "Script is empty", null); return null;}
script += " (function(){return this;})();";
Object thiz;
try{
thiz = engine.eval(script, ctx);
} catch (ScriptException e){
markInvalid(myScript, "Can't execute script", e);
return null;
}
if(thiz==null) {markInvalid(myScript, "Script executed, but context is null", null); return null;}
K ret = (K) ((Invocable)engine).getInterface(thiz, myScript.getScriptInterfaceClass());
if(ret==null) {
markInvalid(myScript, "Script executed, but it's incompatible with required interface", null);
return null;
}else{
myScript.setValid(true);
return ret;
}
}
Wicket doesn't need Nashorn. You can use Wicket 1.5/6.x/7.x/8.x with Java 8.
wicketstuff-nashorn is definitely not needed to run Wicket application.
Without the actual error it is hard for us to tell why it is failing.
Update: why do you use new ScriptEngineManager(null), i.e. null ClassLoader. Better use new ScriptEngineManager() and it will use the context class loader which most probably knows about both classes. Or use new ScriptEngineManager(YourInterface.class.getClassLoader())

Pax Exam how to start multiple containers

for a project i'm working on, we have the necessity to write PaxExam integration tests which run over multiple Karaf containers.
The idea would be finding a way to extend/configure PaxExam to start-up a Karaf container (or more) and deploying there a bounce of bundles, and then start the test Karaf container which will then test the functionality.
We need this to verify performance tests and other things.
Does someone know anything about that? Is that actually possible in PaxExam?
I write the answer by myself, after having found this interesting article.
In particular have a look at the sections Using the Karaf Shell and Distributed integration tests in Karaf
http://planet.jboss.org/post/advanced_integration_testing_with_pax_exam_karaf
This is basically what the article says:
first of all you have to change the test probe header, allowing the dynamic-package
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*;status=provisional");
return probe;
}
After that, the article suggests the following code that is able to execute commands in the Karaf shell
#Inject
CommandProcessor commandProcessor;
protected String executeCommands(final String ...commands) {
String response;
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final PrintStream printStream = new PrintStream(byteArrayOutputStream);
final CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err);
FutureTask<string> commandFuture = new FutureTask<string>(
new Callable<string>() {
public String call() {
try {
for(String command:commands) {
System.err.println(command);
commandSession.execute(command);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
return byteArrayOutputStream.toString();
}
});
try {
executor.submit(commandFuture);
response = commandFuture.get(COMMAND_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace(System.err);
response = "SHELL COMMAND TIMED OUT: ";
}
return response;
}
Then, the rest is kind of trivial, you will have to implement a layer able to start-up a child instance of Karaf
public void createInstances() {
//Install broker feature that is provided by FuseESB
executeCommands("admin:create --feature broker brokerChildInstance");
//Install producer feature that provided by imaginary feature repo.
executeCommands("admin:create --featureURL mvn:imaginary/repo/1.0/xml/features --feature producer producerChildInstance");
//Install producer feature that provided by imaginary feature repo.
executeCommands("admin:create --featureURL mvn:imaginary/repo/1.0/xml/features --feature consumer consumerChildInstance");
//start child instances
executeCommands("admin:start brokerChildInstance");
executeCommands("admin:start producerChildInstance");
executeCommands("admin:start consumerChildInstance");
//You will need to destroy the child instances once you are done.
//Using #After seems the right place to do that.
}

How to check my jboss is started in JAVA?

ex) abc.war is deployed in Jboss.
I want to know that jboss is started or not... in already deployed java source(abc.war).
there is running a thread to check it out.
but I wondering how can I know my jboss is completelly started.
or How to know the end point which jboss is successfully started.
cos I have to execute some method after jboss is completelly on.
jboss5.0 + spring3.0 + jre1.6
EDIT: I just realized that you were aiming at JBoss 5. AFAIK, the below advice works only with JBoss 7.x. Please tell if it is still relevant to you. Otherwise I will delete the answer.
You can use the Jboss Management API for this. HEre is an example of how to access JBoss management using JBoss detyped management (jboss.dmr) library:
final ModelNode request = new ModelNode();
request.get(ClientConstants.OP).set("read-resource");
request.get("recursive").set(true);
request.get(ClientConstants.OP_ADDR).add("subsystem", "deployments");
ModelControllerClient client = null;
try {
client = ModelControllerClient.Factory.create(InetAddress.getByName(MANAGEMENT_HOST),
MANAGEMENT_PORT);
} catch (final UnknownHostException e) {
log.warn("unable to create ModelControllerClient on {}:{}, {}", new Object[] {
MANAGEMENT_HOST, MANAGEMENT_PORT, e });
return;
}
ModelNode response = null;
try {
response = client.execute(new OperationBuilder(request).build());
} catch (final IOException e) {
log.warn("unable to perform operation : {}, {}", request, e);
return;
}
log.info("request returned following results:");
final ModelNode resultNode = response.get(ClientConstants.RESULT);
for (final String key : resultNode.keys()) {
log.info("{} : {}", key, resultNode.get(key));
}
Perhaps JSR-88 would be of assistance, which JBoss supports and even provides example code to note its use?

FOP/ikvm: error "Provider com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl not found"

I have produced a fop.dll from fop-1.0 with ikvm:
ikvmc -target:library -reference:IKVM.OpenJDK.Core.dll -recurse:{myPathToJars}\*.jar -version:1.0 -out:{myPathToJars}\fop.dll
If I use my fop.dll in a Windows Application, everything works perfect.
If I use it in a Class Library, I get the following error:
"Provider com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl not found" at javax.xml.transform.TransformerFactory.newInstance()
The code line is: TransformerFactory factory = TransformerFactory.newInstance();
Here is the code of method:
public static void xmlToPDF(String xmlPath, String xslPath, SortedList arguments, String destPdfPath)
{
java.io.File xmlfile = new java.io.File(xmlPath);
java.io.File pdffile = new java.io.File(destPdfPath);
try
{
// configure fopFactory as desired
FopFactory fopFactory = FopFactory.newInstance();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// configure foUserAgent as desired
// Setup output
OutputStream outputStream = new java.io.FileOutputStream(pdffile);
outputStream = new java.io.BufferedOutputStream(outputStream);
try
{
// Construct fop with desired output format
Fop fop = fopFactory.newFop("application/pdf" /*MimeConstants.MIME_PDF*/, foUserAgent, outputStream);
// Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
java.io.File xsltfile = new java.io.File(xslPath);
Transformer transformer = factory.newTransformer(new StreamSource(xsltfile.getAbsoluteFile()));
// Set the value of a in the stylesheet
if (arguments != null)
{
IList keys = arguments.GetKeyList();
foreach (var key in keys)
{
Object value = arguments[key];
transformer.setParameter(key.ToString(), value);
}
}
// Setup input for XSLT transformation
Source src = new StreamSource(xmlfile);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
}
catch (Exception e1)
{
System.Console.WriteLine(e1.Message);
}
finally
{
outputStream.close();
}
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}
}
I used ikvm-0.46.0.1 to make my fop.dll (based on fop 1.0). I included the following jars:
avalon-framework-4.2.0.jar
batik-all-1.7.jar
commons-io-1.3.1.jar
commons-logging-1.0.4.jar
fop.jar
serializer-2.7.0.jar
xalan-2.7.0.jar
xercesImpl-2.7.1.jar
xml-apis-1.3.04.jar
xml-apis-ext-1.3.04.jar
xmlgraphics-commons-1.4.jar
Any idea why this error occurs? Why is the behaviour different between Windows Application and Class Library?
Addition 10/19/11:
I managed to get working the following:
MyMainPrg (a Windows Forms Application)
MyFopWrapper (a Class Library that calls fop.dll)
But for my case this is not the solution, because in my target project, I have the following structure:
MainCmdLinePrg (a Console Application; calls DLL_1)
DLL_1 (calls DLLsharedFop) {there are several DLLs that can call DLLsharedFop}
DLLsharedFop (calls directly fop.dll; or - I don't care - might call MyFopWrapper)
Unfortunately this construct results in the error.
You can shorten to a pair (ACmdLinePrg,MyFopWrapper): already this does not work! But (MyMainPrg,MyFopWrapper) does...
Here is how I got that error and how I resolved:
My solultion looks like this:
ClientApp (references)--> ClassLibrary1
My ClassLibrary1 public functions are using, but not exposing any IKVM related objects, therefore the caller (ClientApp) did not have to add IKVM references. All is good in compile time.
However in runtime, the situation is different. I got the same exception and realized that ClientApp also needed to reference the correct IKVM dll (IKVM.OpenJDK.XML.Transform.dll) that contains "com.sun.org.apache.xalan.#internal.xsltc.trax" namespace.
I resolved a similar problem by adding the following before the problematic line:
var s = new com.sun.org.apache.xerces.#internal.jaxp.SAXParserFactoryImpl();
var t = new com.sun.org.apache.xalan.#internal.xsltc.trax.TransformerFactoryImpl();
As described here
Do you have the dll with the missing class in your working directory?
If you have the dll then it is a classloader problem. Look in the IKVM wiki. Often the BootClassPathAssemby help.
I was using NuGet Packages of FOP.dll v1.1.0 and IKVM pacakges of v7.1.45 in C#.NET app. I got this issue on Windows 2016 x64 server with error messages like:
------------------------------ Fop.cs (111): Provider com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
not found - at javax.xml.transform.TransformerFactory.newInstance()
Fop.cs (125): Provider
com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl not found
- at javax.xml.parsers.SAXParserFactory.newInstance()\r\n at org.apache.avalon.framework.configuration.DefaultConfigurationBuilder..ctor(Boolean
enableNamespaces)\r\n at
org.apache.avalon.framework.configuration.DefaultConfigurationBuilder..ctor()\r\n
I resolved the problem by adding those two lines at begins of procedure
com.sun.org.apache.xerces.#internal.jaxp.SAXParserFactoryImpl s = new com.sun.org.apache.xerces.#internal.jaxp.SAXParserFactoryImpl();
com.sun.org.apache.xalan.#internal.xsltc.trax.TransformerFactoryImpl t = new com.sun.org.apache.xalan.#internal.xsltc.trax.TransformerFactoryImpl();
helpful link:
https://github.com/KevM/tikaondotnet/issues/21