how to add a file to Java Classpath at Runtime? - java

I am creating a feature file at runtime and trying to access the file once it is created . I have followed all the methods given here .
1. Is there a way to refresh the project at runtime ?
2. Is there any other way to load the file in classpath ?
[Edit] Adding Sample code
public static void createFeatureFile(String featurePath) throws IOException{
FileWriter writer = new FileWriter(featurePath);
writer.append("Feature: Test ");
writer.append("\n");
writer.append("\n");
writer.append("#test");
writer.append("\n");
writer.append("Scenario : add fruits");
writer.append("\n");
writer.append("Given I have 1 apple and 1 orange");
writer.append("\n");
writer.append("Then I add both"");
writer.append("\n");
writer.flush();
writer.close();
File file =new File(featurePath);
addFileAtRunTime(file);
}
private static void addFileAtRunTime(File file) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}

Try this one on for size.
private static void addFileAtRunTime(File file) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}
This edits the system class loader to include the given file.

Related

How can I print the error message into a txt or json file in my directory?

I have a function that save all the error in a errormessage list
public class Util {
private List<String> errorMessages = new ArrayList<>();
public void outputResult(String content) {
logger.error(content);
errorMessages.add(content);
}
}
and my compare function add all the error message to the list,
public void compare(Config source, Config target) {
if (source.getId() != target.getId()) {
util.outputResult("id not equal");
}
// ...
}
And in my main function, I call this compare function and want to save all the error message in a txt or some other file in my current directory
public class MyClass {
public void main() {
compare();
// writeToFile
}
}
This is what I'm doing right now, I convert ByteArrayOutputStream to a string and print it, there a txt file generated but is empty, and I don't want to a string, I want each error message in the list be printed, how can I do that?
ByteArrayOutputStream errorMessages = new ByteArrayOutputStream();
try (FileWriter w = new FileWriter(pathToReport)) {
w.write(errorMessages.toString());
}
File errorMessagesFile = new File(pathToReport);
errorMessagesFile.writeText(errorMessages.toString());
What logger library that you are using? If you use sl4j, you can couple it with log4j by configuring properly to just log the error messages into the file that you have specified in the configuration. I've done some lookup and I find this stackoverflow: where-does-the-slf4j-log-file-get-saved answer provided a template for you to follow on with this setup.

Test File Selection with JUnit/JMockit

I am attempting to test a method that returns a File object using JUnit and JMockit. I am a beginner with both of these.
The problem I am having is that I can't figure out how to properly/successfully mock the implementation method returning a file, since in reality, the user has to actually select a file for the method to return. The error I keep running into is:
java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter
Any suggestions?
Here is a recreation of my implementation:
public final class MyClass {
public static File OpenFile(Stage stage, String title, String fileTypeText, ArrayList<String> fileType) throws Exception {
File file = null;
try {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(title);
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionsFilter(fileTypeText + fileType, fileType);
fileChooser.getExtensionsFilters().add(extFilter);
file = fileChooser.showOpenDialog(stage);
return file;
}
catc (Exception e) {
if(fileType==null) {
...
}
return file;
}
}
}
Here is a recreation of my attempted JUnit test:
#Test
public void TestOpenFile(#Mocked Stage stage) throws Exception {
final ArrayList<String> extensions = new ArrayList<String>();
extensions.add(".txt");
final File file = null;
new Expectations() {{
MyClass.OpenFile(stage, anyString, anyString, extensions); returns(file);
}};
assertEquals(file, MyClass.OpenFile(stage, "some title", "some type", extensions));
}
Your solution is correct, but I would use expectations instead:
public void TestOpenFile(#Mocked FileChooser chooser) throws Exception{
new Expectations() {
{
chooser.showOpenDialog(stage); result = expectedFile;
}};
final File actualFile = MyClass.OpenFile(...);
assertEquals(expectedFile, actualFile);}
I find this easier to understand and write (my personal preference)
I realized that I was approaching the problem incorrectly at first. What I did to resolve this was:
Mock the FileChooser.showOpenDialog method to return a file instead of trying to mock my own method to return a file, which would have defeated the purpose of testing.
final File expectedFile = new File("abc");
new MockUp<FileChooser>() {
#Mock
File showOpenDialog(final Window overWindow) {
return expectedFile;
}
};
final File actualFile = MyClass.OpenFile(...);
assertEquals(expectedFile, actualFile);

Wanted but not invoke: Mockito PrintWriter

Hi I am working on a project and using PrintWriter class for opening and writing in the file. But when I am writing the test case for same it gives following error at Line 153
Wanted but not invoked:
mockPrintWriter.println("ID url1
");
-> at x.y.z.verify(ProcessImageDataTest.java:153)
Actually, there were zero interactions with this mock.
Code: (Uses Lombok Library)
ProcessImageData.java
#Setter
#RequiredArgsConstructor
public class ProcessImageData implements T {
private final File newImageDataTextFile;
#Override
public void execute() {
LineIterator inputFileIterator = null;
try {
File filteredImageDataTextFile = new File(filteredImageDataTextFilepath);
PrintWriter writer = new PrintWriter(newImageDataTextFile);
inputFileIterator = FileUtils.lineIterator(filteredImageDataTextFile, StandardCharsets.UTF_8.displayName());
while (inputFileIterator.hasNext()) {
if(someCondition)
**Line51** writer.println(imageDataFileLine);
//FileUtils.writeStringToFile(newImageDataTextFile, imageDataFileLine + NEWLINE, true);
}
}
} catch (Exception e) {
} finally {
LineIterator.closeQuietly(inputFileIterator);
**LINE63** writer.close();
}
}
ProcessImageDataTest.java
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ProcessImageData.class, FileUtils.class, Printwriter.class })
public class ProcessImageDataTest {
private ProcessImageData processImageData;
private static final String FILTERED_IMAGE_DATA_TEXT_FILE_PATH = "filteredFilepath";
private File FILTEREDFILE = new File(FILTERED_PATH);
private static final File IMAGE__FILE = new File("imageFilePath");
private LineIterator lineIterator;
#Mock
private PrintWriter mockPrintWriter;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
processImageData = new ProcessImageData(Palettes_file, FILTERED_PATH, IMAGE_FILE);
PowerMockito.mockStatic(FileUtils.class);
PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE).thenReturn(mockPrintWriter);
PowerMockito.when(FileUtils.lineIterator(FILTERED_FILE, StandardCharsets.UTF_8.displayName())).thenReturn(lineIterator);
PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false);
}
#Test
public void testTaskWhenIDInDBAndStale() throws IOException {
PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID1 + SPACE + URL2);
processImageData.execute();
List<String> exepctedFileContentOutput = Arrays.asList(ID2 + SPACE + URL1 + NEWLINE);
verify(exepctedFileContentOutput, 1, 1);
}
#Test
public void testTaskWhenIDNotInDB() throws IOException {
PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID3 + SPACE + URL2);
processImageData.execute();
List<String> exepctedFileContentOutput = Arrays.asList(ID3 + SPACE + URL2 + NEWLINE);
verify(exepctedFileContentOutput, 1, 1);
}
private void verify(List<String> exepctedFileContentOutput, int fileWriteTimes, int fileReadTimes) throws IOException {
for (String line : exepctedFileContentOutput){
**Line153** Mockito.verify(mockPrintWriter, Mockito.times(fileWriteTimes)).print(line);
}
PowerMockito.verifyStatic(Mockito.times(fileReadTimes));
FileUtils.lineIterator(FILTERED_IMAGE_DATA_TEXT_FILE, StandardCharsets.UTF_8.displayName());
}
}
I am mocking a new operator for PrintWriter also, injecting using beans. What is the mistake I am doing?? I am stuck on it from long time and not getting the error?
Any help is appreciated.
Updated :
I did changes suggested below and updated the code, but now I get the error:
Wanted but not invoked: mockPrintWriter.print("ASIN2 url1 "); ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageDataTest.verify‌​(ProcessImageDataTes‌​t.java:153)
However, there were other interactions with this mock: -> at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​51) ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​51) ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(Pr‌​ocessImageData.java:‌​58) –
I see 3 issues in your test:
You don't try to mock the correct constructor, indeed in the method execute, you create your PrintWriter with only one argument of type File while you try to mock the constructor with 2 arguments one of type File and the other one of type String.
So the code should rather be:
PowerMockito.whenNew(PrintWriter.class)
.withArguments(IMAGE_FILE)
.thenReturn(mockPrintWriter);
To be able to mock a constructor you need to prepare the class creating the instance which is ProcessImageData in this case, so you need to add ProcessImageData.class in the annotation #PrepareForTest. (I'm not sure ProcessImageDataTest.class is needed there)
The field lineIterator should be annotated with #Mock.
Instead of verifying print with a new line, you should verify directly println without new line it is much less error prone.
I simplified your code to show the idea.
Assuming that ProcessImageData is:
public class ProcessImageData {
private final File newImageDataTextFile;
public ProcessImageData(final File newImageDataTextFile) {
this.newImageDataTextFile = newImageDataTextFile;
}
public void execute() throws Exception{
try (PrintWriter writer = new PrintWriter(newImageDataTextFile)) {
LineIterator inputFileIterator = FileUtils.lineIterator(
newImageDataTextFile, StandardCharsets.UTF_8.displayName()
);
while (inputFileIterator.hasNext()) {
writer.println(inputFileIterator.nextLine());
}
}
}
}
My unit test would then be:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProcessImageData.class, FileUtils.class})
public class ProcessImageDataTest {
private File file = new File("imageFilePath");
private ProcessImageData processImageData;
#Mock
private PrintWriter mockPrintWriter;
#Mock
private LineIterator lineIterator;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
processImageData = new ProcessImageData(file);
PowerMockito.whenNew(PrintWriter.class)
.withArguments(file)
.thenReturn(mockPrintWriter);
PowerMockito.mockStatic(FileUtils.class);
PowerMockito.when(
FileUtils.lineIterator(file, StandardCharsets.UTF_8.displayName())
).thenReturn(lineIterator);
PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false);
}
#Test
public void testExecute() throws Exception {
PowerMockito.when(lineIterator.nextLine()).thenReturn("Foo", "Bar");
processImageData.execute();
Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Foo");
Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Bar");
}
}
For more details please refer to How to mock construction of new objects.
how can I add verification in unit test for writer.close?
One way could be to simply check that close() at be called once by adding the next line to your unit test:
Mockito.verify(mockPrintWriter, Mockito.times(1)).close();
Your construction of the PrintWriter doesn't match the mock. You told PowerMockito to return your mock like this:
PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE , StandardCharsets.UTF_8.name()).thenReturn(mockPrintWriter);
So you would have to say:
new PrintWriter(IMAGE_FILE, "UTF-8"); // 2 arguments
But instead in your execute method in the code that is being tested, you do:
PrintWriter writer = new PrintWriter(newImageDataTextFile); // only 1 argument
So you either need to change the PowerMockito withArguments clause, or you need to add "UTF-8" to the constructor invocation in the execute method.

detect main inside a jar using java code.

I am trying to detect which class inside a jar contains main or a supplied method name (if possible).
At the moment I have the following code
public static void getFromJars(String pathToAppJar) throws IOException{
FileInputStream jar = new FileInputStream(pathToAppJar);
ZipInputStream zipSteam = new ZipInputStream(jar);
ZipEntry ze;
while ((ze = zipSteam.getNextEntry()) != null) {
System.out.println(ze.toString());
}
zipSteam.close();
}
This will allow me to get packages and classes under these packages, but I do not know if it is possible to even get methods inside classes.
Further, I do not know if this approach is even good for a case of several pkgs inside the jar, since each package can have a class with main in it.
I would appreciate any ideas.
Thanks to fvu's comments, I ended up with the following code.
public static void getFromJars(String pathToAppJar) throws IOException, ClassNotFoundException
{
FileInputStream jar = new FileInputStream(pathToAppJar);
ZipInputStream zipSteam = new ZipInputStream(jar);
ZipEntry ze;
URL[] urls = { new URL("jar:file:" + pathToAppJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
while ((ze = zipSteam.getNextEntry()) != null) {
// Is this a class?
if (ze.getName().endsWith(".class")) {
// Relative path of file into the jar.
String className = ze.getName();
// Complete class name
className = className.replace(".class", "").replace("/", ".");
Class<?> klazz = cl.loadClass(className);
Method[] methodsArray = klazz.getMethods();
}
}
zipSteam.close();
}
I removed the code that uses the methods found, since it is not important for this answer

Spring - validate that all message resources are well configured

We need to add some code to be executed on application load in order to validate that all the messages.properties elements are well defined for all languages.
Is this possible?
Steps: dynamically read on application load all the spring message codes from JSP or java classes then pass through all message resources properties files and validate that nothing is missing from them.
We ended up doing this manually but without using any library.
Steps:
have all the keys used in Java classes or JSP defined in a constant file
Read them using Java .class properties:
Field[] fields = Constants.class.getFields();
String filed[i].get(Constants.class);
Read all messageResources.properties file names from the project using:
String pathToThisClass = MessageResourcesValidator.class.getProtectionDomain().getCodeSource().getLocatin().getPath();
File filePath = new File(pathToThisClass);
String[] list = filePath.list(new DirFilter("(messages).*\\.(properties)"));
DirFilter is a normal class implementing Java's FileNameFilter
Create a class that read the properties from a file using its file name:
public class PropertiesFile{
private Properties prop;
public PropertiesFile(String fileName) throws Exception
{
init(fileName);
}
private void init(String fileName) throws Exception
{
prop = new Properties();
try (InputStream input = getClass().getClassLoader().getResourceAsStream(fileName);)
{
if(input == null)
{
throw new Exception("Enable to load properties file " + fileName);
}
prop.load(input);
}
catch(IOException e)
{
throw new Exception("Error loading properties file " + fileName);
}
}
public List<String> getPropertiesKeysList()
{
List<String> result = new ArrayList<>();
Enumeration<?> e = prop.propertyNames();
while(e.hasMoreElements())
{
result.add((String) e.nextElement());
// String value = prop.getProperty(key);
}
return result;
}
}
The part that does the comparison should be something as the following code that calls the above methods:
List<String> msgResourcesFiles = getMessageResourcesFileNames();
List<String> codeKeys = getListOfCodeMessageResources();
PropertiesFile file = null;
List<String> propKeys = null;
for(String fileName : msgResourcesFiles)
{
file = new PropertiesFile(fileName);
propKeys = file.getPropertiesKeysList();
for(String key : codeKeys)
{
if(!propKeys.contains(key))
{
throw new Exception("Missing key " + key);
}
}
}
Note: or another workaround would be to compare all message resources files to a default one and this way we minimize the code needed from the above explanation.

Categories