Hi I am working on a Maven project having dependency on a external jar which has a class ConfigLoader having following loader() method.
public class ConfigLoader {
public void initialize() {
loader();
}
private static void loader() {
URL configURL = ConfigLoader.getClass().getResource("runtimeConfiguration.xml");
//some other method calls to which configURL is an argument.
}
//other methods of ConfigLoader class
}
and the directory structure is like this -
src
|...main
|.......java
|.......resources
|................dev
|................prod
both dev and prod have a file named runtimeConfiguration.xml
and the code which uses this class is
public class Application {
private Application application;
public static void main(String []args){
application = new Application();
application.invokeConfigLoader();
//additional code
}
private void invokeConfigLoader() {
configLoader.initialize();
}
}
The error I get is
could not find: runtimeConfiguration.xml
and the exception is thrown at the getResource() line in the class from jar.
I have tried adding the dev folder to classpath but still the same error. I want to run this code from linux terminal, and the command I am giving from trunk directory (where all my exernal jars and resource folder sits after maven build) is -
java -cp /resources/dev/*:configuration-loader.jar
I am using intelliJ 2017.2 and also tried to add the resources/dev folder as module dependency, but I keep on getting the same error. The resources folder is added as a library via project structure settings. I tried to search a lot but have not found any question with this issue. Kindly help me out as I am new to this environment based development.
Thanks!
ConfigLoader.getClass().getResource("runtimeConfiguration.xml"); will try to get runtimeConfiguration.xml from the same package a the ConfigLoader is defined and not from the root of classpath. Try appending / to runtimeConfiguration.xml.
This should work ConfigLoader.getClass().getResource("/runtimeConfiguration.xml"); or ConfigLoader.getClass().getResource("/dev/runtimeConfiguration.xml"); depending how you are adding resources to your classpath.
See javadoc for more.
Related
I need to have a jar file located in a main/assets directory within an Android project. It is important the jar file is located there.
With my main Android project is there a way to reference this jar file in my code and to use its classes?
To be clear I don't want to add the jar to the main project once compiled.
EDIT: I have tried the link below and it seems to load the Class file I've stated. But I'm strugging how to define constructor arguments for the dynamically loaded Class.
android-custom-class-loading-sample
EDIT2
Nearly there. I've confirmed the class is loaded from my classes.jar. I'm stuck instantiating it though.
On the licenseValidatorClazz.getConstructor line I get the error below. I'm guessing I'm missing something from my Interface file?
java.lang.NoSuchMethodException: [interface com.google.android.vending.licensing.Policy, interface com.google.android.vending.licensing.DeviceLimiter, interface com.google.android.vending.licensing.LicenseCheckerCallback, int, class java.lang.String, class java.lang.String]
public Class licenseValidatorClazz = null;
public LicenseValidator validator;
...
// Initialize the class loader with the secondary dex file.
DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
optimizedDexOutputPath.getAbsolutePath(),
null,
mContext.getClassLoader());
try {
// Load the library class from the class loader.
licenseValidatorClazz = cl.loadClass("com.google.android.vending.licensing.LicenseValidator");
validator = (LicenseValidator) licenseValidatorClazz.getConstructor(Policy.class,DeviceLimiter.class,LicenseCheckerCallback.class,int.class,String.class,String.class).newInstance(ddd, new NullDeviceLimiter(),
callback, generateNonce(), mPackageName, mVersionCode);
} catch (Exception exception) {
// Handle exception gracefully here.
exception.printStackTrace();
}
I have an Interface which contains the functions to pass to the loaded class.
public interface LicenseValidator
{
public LicenseCheckerCallback getCallback();
public int getNonce();
public String getPackageName();
public void verify(PublicKey publicKey, int responseCode, String signedData, String signature);
public void handleResponse(int response, ResponseData rawData);
public void handleApplicationError(int code);
public void handleInvalidResponse();
}
TO use an external jar to be associated with your application and use it during runtime, it needs to be in dalvik format since normal jars cannot work under dalvikVM.
Convert your files using the dx tool
using aapt cmd , add those classes.dex to your jar file.
Now this jar which contains files in dalvik format can be loaded into our project.
Here is a post which explains the procedure to accomplish it.
There are steps to accomplish this.
You have to make a copy of your JAR file into the private internal storage of your aplication.
Using the dx tool inside the android folder, you have to generate a classes.dex file associated with the JAR file. The dx tool will be at the location /android-sdks/build-tools/19.0.1 (this file is needed by the Dalvik VM, simply jar can not be read by the dalvik VM))
Using the aapt tool command which is also inside the same location, you have to add the classes.dex to the JAR file.
This JAR file could be loaded dynamically using DexClassLoader.
If you are making a JAR from any one your own library, you have to do this steps (1-4) every time when there is a change in your library source code. So you can automate this steps by creating a shell script(in Mac/Linux/Ubuntu) or batch scripts(in Windows). You can refere this link to understand how to write shell scripts.
Note : One situation for implementing this method is, when it is impossible to add the JAR files directly to the build path of core project and need to be loaded dynamically at run time. In normal cases the JAR files could be added to the build path.
please check this link for the detailed code and implementation.
How to load a jar file at runtime
Android: How to dynamically load classes from a JAR file?
Hope this helps!!
You should try out the Services API - java.util.ServiceLoader
You define a service interface and its implementations in your jar.
package com.my.project;
public interface MyService { ... }
public class MyServiceBarImpl implements MyService { ... }
public class MyServiceFooImpl implements MyService { ... }
Then you define the services contained within the jar file in the META-INF/services/ directory. For instance, in the file 'META-INF/services/com.my.project.MyService', you list the provider classes.
# Known MyService providers.
com.my.project.MyServiceBarImpl # The original implementation for handling "bar"s.
com.my.project.MyServiceFooImpl # A later implementation for "foo"s.
Then, in your main codebase, you can instantiate a MyService instance with the ServiceLoader:
for (MyService service : ServiceLoader.load(MyService.class)) {
//Perform some test to determine which is the right MyServiceImpl
//and then do something with the MyService instance
}
These examples are taken more-or-less straight from the API, although I've changed the package names to make them slightly less annoying to read.
I have my custom maven plugin, which has to run tests programmatically on a test phase for example. So I have something like that
#Mojo(name = "aggregate", requiresDependencyResolution = ResolutionScope.RUNTIME)
public class AcceptanceTestMojo extends AbstractMojo {
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
TestExecutor testExecutor = new TestExecutor();
testExecutor.setTestClasses(new Class[]{TestClass.class});
testExecutor.run();
}
}
So the problem comes because the TestClass.class is from another maven module and actually the resources which I want to get are loaded in that module classpath. In that TestClass I have the following method:
public Object[][] retrieveFile() throws IOException {
String[] issuesKeys = IOUtils.toString(
Thread.currentThread().getContextClassLoader().getResourceAsStream("fileName"))
.split("\\n");
....
....
}
If I build the module where the TestClass belongs to everything is working fine, because Thread.currentThread().getContextClassLoader() is loading the correct ClassLoader, but if run it with my plugin as I run the test programatically Thread.currentThread().getContextClassLoader() is loading the classpath of my plugin, so the file I want to retrive is not there and a RuntimeException is thrown.
So my question is how to get the correct ClassLoader so that to be able to get the file or is there a way to load files in classpath manually with java?
I found one solution- I modified the currentThread ClassLoader- I got all required classes from the classpath of the maven project I am executing the plugin on. This is possible with injecting the MavenProject bean:
#Component
private MavenProject project;
I am trying to get gwt-test-utils to work. I set up the project in the following way:
src/main/java : all the java source code
src/test/java : the test source code
src/test/resources : resource files for the tests
I am building my project with gradle and eclipse. Gradle uses these directories correctly by default and I added all three of them as source directories to Eclipse.
I have successfully built and run the project and was able to execute some plain old JUnit tests as well as a GWTTestCase, so I think I set up the project and its dependencies correctly.
Now I wanted to use gwt-test-utils for some more advanced integration tests. To do so I did the following:
Add the gwt-test-utils and gwt-test-utils-csv to my dependencies
gwtTestUtilsVersion = '0.45'
testCompile group:'com.googlecode.gwt-test-utils', name:'gwt-test-utils', version:gwtTestUtilsVersion
testCompile group:'com.googlecode.gwt-test-utils', name:'gwt-test-utils-csv', version:gwtTestUtilsVersion
Add a gwt-test-utils.properties file to the directory src/test/resources/META-INF with the following content:
path/to/my/module = gwt-module
Added a class that extends GwtCsvTest to a package in the src/test/java directory. It is modeled after the second example in HowToWriteCsvScenario from the gwt-test-utils project wiki, replacing occurrence of their example classes with mine. It looks like this
#CsvDirectory(value = "gwtTests")
public class LoginLogoutTest extends GwtCsvTest
{
#Mock
private MainServiceAsync mainService;
private AppController appController = new AppController();
#CsvMethod
public void initApp()
{
appController.onModuleLoad();
}
#Before
public void setup()
{
GwtFinder.registerNodeFinder("myApp", new NodeObjectFinder()
{
#Override
public Object find(Node node)
{
return csvRunner.getNodeValue(appController, node);
}
});
GwtFinder.registerNodeFinder("loginView", new NodeObjectFinder()
{
#Override
public Object find(Node node)
{
return csvRunner.getNodeValue(appController.getRootPresenter().getCurrentlyActiveSubPresenters().iterator().next().getView(), node);
}
});
addGwtCreateHandler(createRemoteServiceCreateHandler());
}
}
added a csv-file for configuring the test to src/test/resources/gwtTests with the following content
start
initApp
assertExist;/loginView/emailTextBox
I tried executing it via the Eclipse's Run As > JUnit Test and indirectly via gradle build (which executes all the test cases, not just this one). Both lead to the same error:
ERROR GwtTreeLogger Unable to find type 'myPackage.client.AppController'
ERROR GwtTreeLogger Hint: Check that the type name 'myPackage.client.AppController' is really what you meant
ERROR GwtTreeLogger Hint: Check that your classpath includes all required source roots
The AppController class is the entry-point configured in the module I configured in gwt-test-utils.properties, which makes me think that configuration works correctly and the rest of the setup (dependencies and all) work as well.
In an earlier version I used the same file as a subclass of GWTTestCase and created an AppController instance in the same way. That worked, so I'm pretty sure the class path is setup correctly to include it as well. I also tried changing it back to the previous version just now and it still works.
I have no clue why the class is not found. Is there anything gwt-test-utils does differently which means I need to specifically set the class path for it? Otherwise it should just work, since both gradle and eclipse know about all the relevant source folders and dependencies.
I have a file called command.xml, when I work with NetBeans everything works fine.
But when I create the jar file I have an exception that the file is not found.
Example I have replaced this assignment:
String commandPath = "command.xml";
with this:
String commandPath = getClass().getResources("command.xml").getPath();
but it does not work.
I supose that "command.xml" right now is in your project folder (same level where src/ is). To use the resource loading you should move the file in the same folder where the class of the object is that invokes getClass().
Consider you have this class
package my.package
public class Test {
public Test() {
String commandPath=getClass().getResources("command.xml").getPath();
}
}
command.xml should be in
src/my/package/
I have this test fixture I want to run with Fitnesse and it involves using Spring. I haven't been able to load the spring application context with the ClasspathXmlApplicationContext, and I'm sure is a classpath configuration thing that I just haven't figured it out.
So here's my setup.
As you can see, the fitnesse.jar is inside the project, so I can run the fitnesse server and the tests anywhere I have a working copy of the project (all the wiki files are inside the FitNesseRoot folder). The bin is the output folder of the project (where all the .class are).
Now, the code:
InventarioQueryTest (wiki page from Fitnesse, notice the !path declarations)
!define TEST_SYSTEM {slim}
!path ../bin
!path ../web/WEB-INF/lib/**.jar
|import |
|com.softclear.inventario.test.fitnesse|
|Query:listar status |
|id|nombre|entidad|descripcion|
ListarStatus.java (the text fixture invoked by Fitnesse)
public class ListarStatus {
private ServicioStatus serv;
private ClassPathXmlApplicationContext ctx;
//fitnesse calls the constructor
public ListarStatus(){
ctx = new ClassPathXmlApplicationContext(new String[] {
"applicationContext-ListarStatus.xml",
"applicationContext-dao.xml",
"applicationContext-hibernate.xml"});
//performs dependency injection of DAO and HibernateSession
serv = (ServicioStatus) ctx.getBean("servicioStatus");
}
//and the query method is the test
public List<Object> query() {
List<Status> lista = serv.listarStatus();
QueryResultBuilder builder = new QueryResultBuilder(Status.class);
QueryResult result = builder.build(lista.iterator());
return result.render();
}
}
I run fitnesse with java -jar from the working copy of my project. And when I run the test, this is the command that fitnesse executes:
java -cp fitnesse.jar;../bin;C:\Dev\WS\softclear\SistemaInventario\fitnesse\..\web\WEB-INF\lib\ajax\AjaxFileUpload-0.03.jar;%the.rest.of.the.web-inf/lib.jars...% fitnesse.slim.SlimService 8086
And all that produces this error in the test:
java.io.FileNotFoundException: class path resource [applicationContext-ListarStatus.xml] cannot be opened because it does not exist
As fas as I understand, the !path ../bin in the wiki should indicate all the subfolders and stuff to be included in the classpath (the java -cp call), but apparently it doesn't...
Any ideas? Thanks a lot for your time!
Ok so I resolved it, by doing this in the ListarStatus class:
public ListarStatus() {
ctx = new ClassPathXmlApplicationContext(new String[] {
"/com/softclear/inventario/test/fitnesse/applicationContext-ListarStatus.xml",
"applicationContext-dao.xml",
"applicationContext-hibernate.xml"});
serv = (ServicioStatus) ctx.getBean("servicioStatus");
}
Notice that the applicationContext-ListarStatus.xml file has a relative path and not just the name of the file.
Turns out that ClassPathXmlApplicationContext DOES NOT search anywhere in the classpath like I understood (read this, the part of the ClassPathXML...: http://freejavaclass.com/articles/j2ee/spring/spring_loading_types_ways.jsp). At least not in Spring 2.
It had nothing to do with Fitnesse, it was all Spring...