I am using JAVA to create a log file, but after creating it, when I assert its existence, I get back a java.lang.AssertionError. I must be doing something simply wrong but I do not know what. Here is the code:
File testLogFile = new File("/home/ninad/eclipse-workspace/Log.txt");
testLogFile.createNewFile();
service = builder.withLogFile(testLogFile).build();
service.start
assertTrue(testLogFile.exists());
I can think of a few possible explanations:
You are not checking the result of the createNewFile() call. It returns true if the file did not exist before AND it has been successfully create.
By my reading of the javadoc, the method should throw an IOException if it tries to create the file and fails. But the flipside is that if you don't test the result of the call, you can't be sure that you got a new file.
The builder or the service could be removing or renaming the logfile.
If the code was part of a multi-threaded application, then another thread could have removed / renamed the file.
The file could (in theory) have been removed / renamed by another application.
You may have (OS-level) permission to create the file, but not test for its existence. (It seems a bit far-fetched ... but some OSes have "complicated" permissions systems.)
There could be other things I haven't thought of. If you provided an MCVE (including the "builder" implementation) we could check.
Related
I want to implement a function that will take package name as input and list all the contents(only files) inside that package.
public List<String> getContents(String packageName) {
...
}
Example input
packageName = com.spring.com.demo
Expexted output
Class1.java
Class2.java
...
What is the best way to accomplish this task?
You're talking about java's 'classloader' system, which is a slight misnomer, in that it can also load resources other than classes. Point is, classes are a resource that are located somewhere, and the JVM itself needs to find them. After all, when you are running your main class and it refers to 'new Foobar()', the jvm needs to find Foobar.class somehow, read the bytes, and turn them into a new class definition.
Java's classloader system is generalized in two ways:
You can call on it to find you stuff.
You can for example write:
MyApp.class.getResource("icons/share.png")
and get a URL object you can pass straight to e.g. ImageIcon. This way, you can ship your icons for your GUI app together with your class files, and it's completely unified: However the system is loading the classes, be it from disk, from inside a jar file, from eclipse's module system if it's an eclipse plugin, or from the network - this way you're loading your images from the same place.
You can make your own
Let's say you want to write a system that loads classes (and other resources, like images) directly from the web. You can do that: You can make your own ClassLoaders.
Now for the crux of the matter
That means ClassLoader is an abstract concept that lists which features it has. It's like any other interface / abstract class in that regard: It's a template that defines what you can do with one, so that anybody can provide you with an implementation of it.
Here's the crucial thing you must understand so that you know why what you want is impossible (and why the commonly called out 'reflections' library is a hack that doesn't universally work):
The ClassLoader abstract simply has no list command.
Hence, listing? Simply not possible. The only command it does have is 'load Resource X', X being some path-like string. That is all it has. The java classloader system is never in need to 'list all classes in a package', not even when there's a star import (which is just a thing javac knows about, at the class file level star imports aren't a thing). The JVM just needs to e.g. load resource '/java/lang/String.class' - hence, the command 'here is a path, please give me the bytes for it' is all that is neccessary.
The solution to have lists anyway
During compilation, the abstractions do support 'list'. After all, the compiler really does just read java files from a directory (which supports 'list all files inside it'), you can't for example tell the compiler 'please compile all .java files in this .jar file). So, at compile time, you can make a list of resources.
So here's the trick: Save that in a text file and ask for the text file during runtime. Then translate each line in the text file to the full resource path and then ask for each of those. Thus, using just the one API call you have available to you at runtime ('load resource at path X'), you can have a list system anyway. It's just that during the compilation/build/packing step you need the tools that compile/build/pack to do some work and make you a text file with the details.
This is called the SPI (Service Provider Interface) system and java itself uses it - it's how JDBC drivers and e.g. charset implementations are found.
You can use this yourself in this three step process:
Define an interface or abstract class that serves as the thing 'providers' will implement/extend. Let's say it is com.ranjan.MyService`.
At the provider end: Write an implementation for it. Let's say it's com.zwitserloot.ServiceImpl.
During compilation, ensure that in the same place the class files end up (e.g. in the jar file for example), there's META-INF/services/com.ranjan.Myservice (a text file). This file contains the fully qualified class name of each 'provider' class: com.zwitserloot.ServiceImpl is what's on the first (and only) line.
At runtime: Use java.util.ServiceLoader and it'll take care of everything.
Your specific use case
From comments it seems like you don't really need to 'list classes', you have a bunch of classes and need to know if they are 'valid', for some definition of 'valid'. You can either just Class.forName them, though this will also initialize them (run its static initializers). Alternatively, you can run YourOwnClass.class.getResource("com.spring.com.demo.Class1.class"), and check that [A] you get an actual resource (and not null, indicating it doesn't exist), and [B] do whatever validation you want to do on this. For example, toss it through bytebuddy or ASM or some other class format editor and check if it can parse it.
I am trying to write an annotation processor that generates source files, but will not overwrite source files that were generated during a previous run of the annotation processor.
Because I am just learning, I have created an annotation processor as described by Ryan Harter in the following video: https://www.youtube.com/watch?v=IPlDL4EsY08.
I want to be able to generate a source file once, and then allow it to be edited manually by a developer without fear that the manual changes will be overwritten by subsequent runs of the annotation processor. This may not be the norm, but I can think of several use cases where it would prove beneficial.
The specific piece of code within my AbstractProcessor subclass that I wish to modify is:
try {
JavaFile file = JavaFile
.builder(builderType.packageName(), builder)
.build();
file.writeTo(filer);
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR, "Failed to write file for element", el);
}
Right now, it seems to me that all of the files in the generated source folder are getting deleted every time I run the build task for my gradle project. This means that any code I write in the annotation processor to check for the existence of a given generated source file will always return a negative result, even if the generated source file existed prior to running the build task. Is there any way to prevent the generated source folder from getting scrubbed every time you rerun javac with an annotation processor? Or is there a better way to achieve what I am trying to accomplish?
The output of an annotation processor is considered a product of compilation. Just like class files, these are [A] kept out of version control by default by all relevant systems, standards, and style guides, and [B] considered irrelevant, deletable chaff, in an aggressive fashion. Any clean command will delete these, they are overwritten with abandon, and tools may just decide to delete them for hard to discern reasons: They all are assumed to have the property that they don't contain anything important, they are merely a product of a process; a process that can be easily repeated.
For example, these files end up in src/generated or generated_src. Editing this file makes them not (entirely) generated, and that, in turn, means your codebase is now a lie: It has non-generated source files in a directory that strongly suggests they are generated.
Pain then ensues; pain that cannot be solved.
The solution is to not have these files in generated folders; they SHOULD be checked into version control, and they should NOT be considered trivially deletable chaff by tools (IDEs, build systems, etc). However, the annotation processor system does not have a baked in concept of such a directory.
The filer does let you get at the source file itself, so you could consider writing it out to there, that seems like the safest bet.
Note that other systems that work like yours are called 'skeleton' systems or 'scaffolding' systems: For example, maven's archetype system.
None of the many I know use annotation processors to do the job. You may simply be using the wrong toolchain.
Another solution is to import the custom code into a file that is then considered fully generated. For example, have the following rule:
You annotate something like so: package com.foo; #DbModel class PersonTemplate {String name; LocalDate dateOfBirth;}
The tool will then generate a source file containing package com.foo; public class Person { public String getName() { ... }} and a lot more boilerplate and DB query methods and more.
This file will have a comment generated at the top: // Generated code. Don't edit this code; add methods to PersonExtras instead
During your AP's compile run, you scan for a class named com.foo.PersonExtras. If it exists, you scan for static methods inside it. For every such method, you check if the first arg is Person. For example, public void foo(Person p) {}. If it is, you generate an instance method in Person that links to it: public void foo() { PersonExtras.foo(p); }. If it's not, you generate a static method in Person that links to it.
Your Person code is now an artefact of compilation and can be fully recreated at will by your AP with no user input, and yet it can be extended. The PersonExtras class can be placed in source control and is just in your usual src dir, and Person.java won't be in source control and can be deleted at will by tools.
In other words, 3 options:
Use the filer to find the source dir and generate your files there. This may not succeed and is a bit weird.
Don't write this product as an Annotation Processor, but as a stand-alone tool or plugin into an existing scaffolding generator system like maven's archetypes.
Solve the problem of having the produced classes be extensible in some other way, for example by using yet another class's fields and methods as a guide for how to generate the code: Thus ensuring that the source files your AP makes can remain 'intended to never be edited by human hands'.
How should you handle a FileSystemAlreadyExistsException when calling FileSystems.newFileSystem?
One way would be to use the already created FileSystem (getFileSystem​), but then you could run into problems when the original creator closes it while you are still using it.
In case there is no generic answer to this question, then what about ZipFileSystems? Let's say I want to create one for a zip file and I do not know and cannot control whether a FileSystem already exists for this specific zip file.
Is there a reliable way to handle a FileSystemAlreadyExistsException?
Sorry for being late here, but I just ran into this myself. There are several versions of the FileSystems.newFileSystem() call, some versions throw FileSystemAlreadyExistsException, some do not. I found that using the version that accepts a Path object did not throw the exception and allowed me to work around the issue I was having.
Try putting a try/catch block around the code that is causing the exception.
I know that there is a "Check if a folder is empty", but it does not check for existing of the folder.
But to use it in Pentaho is more complicated. When creating a Job rather than a transform, straight Java is not directly available (that I know of). The good news is PDI's JavaScript interpreter is Rhino. That means all Java's objects and classes are available to JavaScript. As such the check is pretty easy.
Add a variable or parameter in your job and call it something like dirpath and give it a path to evaluate. Then add a JavaScript step to the job and add put the following code in it:
dirpath = parent_job.getVariable("dirpath");
fileobj = new java.io.File(dirpath);
fileobj.isDirectory();
Control will flow down the Success or Failure paths from this step based on the truth of the last line.
Pentaho will likely add that capability to their Check if File Exists step soon, but in the mean time, this will work. OTOH, might be another good example of a custom plugin that could be written.
The isDirectory() method of the File Object should do, what you need.
The Api writes:
Returns:
true if and only if the file denoted by this abstract pathname exists and is a directory; false otherwise
--> http://docs.oracle.com/javase/6/docs/api/java/io/File.html#isDirectory%28%29
On Job level you can use the step 'Checks if files exist' for checking the existance of files but folders aswell.
The goal with my program is to have it save when closed, and reloaded when opened.
I have a driver (which contains all of the graphics) and I want it to create and save a file. I've seen numerous tutorials on the internet, but what they fail to explain is how to correctly implement this system in an actual program.
Do I create the OutputStrema in my main method? Do I need to check if a file has been created and if not create one, and if so read from it? How do I accomplish all of this? Should I have a WindowListener for quitting so that it can save all of the data?
Thanks
Yes, a WindowListener sounds like a good idea. One way to save the state of a program is to use Properties. Please have a look at the tutorial linked to above. I'm not sure what to recommend for your "graphics". Please tell us more details about just what you mean here.
Edit
Do I create the OutputStrema in my main method?
you're question re creating the OutputStream in the main method is asking about program structure that we know nothing about. My gut tells me that i wouldn't create anything like this in the main method, even if the JFrame is created there (or in a static method called from main). The OutputStream would be created in the class that implements the WindowListener, and this can be its own stand alone class. You want to make the main method as small as possible.
Do I need to check if a file has been created and if not create one, and if so read from it?
Possibly. This question revolves around what you're going to do with the stored information once created. Perhaps you'll search for it and read it on program start up? I don't know as it all depends on your needs, something you'll have to figure out.
How do I accomplish all of this? Should I have a WindowListener for quitting so that it can save all of the data?
If this is a Swing application, then yes, a WindowListener would help you control your application's closing.
Do I create the OutputStrema in my main method?
It would be better to create the stream at the point where you are saving the state.
When my program runs it is going to take in the saved data file with its ObjectInputStream. Do I put the code to accomplish this in my Main method?
Sounds like a good choice. Basically, you need to do this before you attempt to do something that needs that data. Anything that achieves this will work (though doing it using static initialization is a bad idea ...)
Do I need to check if a file has been created and if not create one, and if so read from it?
This question is confusing writing the state file and reading it. They occur at different points in the lifecycle, and use different code to do the task.
There is no point checking to see if a save file exists before creating one ... unless you propose to rename the existing save file.
Conversely, if a save file doesn't exist when you start the application, then the constructor that attempts to open it will throw a FileNotFoundException. Just catch the exception and skip the code that reads the saved state.
... if there has not been a file created yet, will this cause an error?
Yes. A FileNotFoundException; see above. So your code has to deal with that, or test to see if the file exists before attempting to open in; see File.exists() and related methods.
Should I have a WindowListener for quitting so that it can save all of the data?
That sounds like part of the solution. (But what about the case where the program crashes or is killed? Do you want to save state in those cases ... or not?)
A couple of things to beware of:
Many GUI-related objects do not implement Serializable, and therefore cannot be saved using an ObjectOutputStream. Threads, streams, sockets and a few other things can't be serialized either.
When you save instances of classes using ObjectOutputStream, change the classes or their names, and then attempt to reload them using ObjectInputStream, you are liable to run into trouble with saved instances not matching the new versions of the classes. If you have to be able to read that serialized state you are in trouble.