Can I store an XML file inside a jar file? - java

I built an Jar using Maven.
The behavior I am trying to implement is: when the user uses the command create , I want to store an XML file inside a a folder of the jar. Is it possible to do it?
Let's say this is a project and I added the jar of the migration tool to it.
I want to be able to see and edit the properties file

3-It has some things that need to be altered like for example
migration files and the file with the database information
Not 100% sure if I understood your requirements correctly, but I've implemented some utility classes which support:
default config in JAR
config in installation directory
config in user directory
simple command line arguments/ switches support
and more...
Maybe this helps.
public static void main(String[] args) throws URISyntaxException, IOException, MissingPropertyException, Exception {
CommandLineArgs commandLineArgs = CommandLineArgs.parseCommandLineArgs(args);
DromblerClientStarter<DromblerClientConfiguration> main = new DromblerClientStarter<DromblerClientConfiguration>(new DromblerClientConfiguration(commandLineArgs)) {
#Override
protected ApplicationInstanceListener getApplicationInstanceListener() {
return additionalArgs -> {
// additionalArgs not handled
};
}
};
if (main.init()) {
main.start();
}
}
Source code: https://github.com/Drombler/drombler-commons/tree/master/drombler-commons-client/drombler-commons-client-startup-main
Maven:
<dependency>
<groupId>org.drombler.commons</groupId>
<artifactId>drombler-commons-client-startup-main</artifactId>
<version>1.0</version>
</dependency>
Javadoc: https://www.drombler.org/drombler-commons/1.0/docs/site/apidocs/org/drombler/commons/client/startup/main/package-summary.html

Related

FileNotFoundException when running wiremock from jar file

I am running a spring boot application with wiremock. My files structure is like this:
project/main/
- java/package/Wiremock.java
- resources/wiremock/__files/file.json
Inside Wiremock.java I am calling WireMockServer like this:
WireMockServer wiremockServer = new WireMockServer(WireMockConfiguration.wireMockConfig()
.withRootDirectory(getClass().getResource("/wiremock").getPath())
.port(port));
wiremockServer.start();
wiremockServer.stubFor(get(urlEqualTo("/myurl"))
.willReturn(aResponse()
.withBodyFile("file.json")
.withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.withStatus(HTTP_OK)));
When I am running it locally it works as expected.
When I compile the app to a jar file , a jar file /Users/user/project-0.0.1-SNAPSHOT.jar is generated with the structure:
BOOT-INF/classes/
- wiremock/__files/file.json
- package/Wiremock.class
But when I run the jar file , I'm getting the following error:
java.lang.RuntimeException: java.io.FileNotFoundException: /Users/user/jar:file:/Users/user/project-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/wiremock/__files/file.json (No such file or directory)
Please help, thanks
if this path is correct?
/Users/user/jar:file:/Users/user/project-0.0.1-SNAPSHOT.jar!/BOOT-
INF/classes!/wiremock/__files/file.json (No such file or directory)
I find there is one more "!" after XXXX.jar and classess.
I just meet the same issue today, when i run wire mock in IDEA, it works. but when i run the application by java -jar mode, wired mock server cannot find the json mock file. the root cause of this issue is that when initialization of wire mock server, it will found the json file by com.github.tomakehurst.wiremock.common.ClasspathFileSource
class, it will recursively add files to list of the config path which you specified. the logic of add file is showed below like this.
public List<TextFile> listFilesRecursively() {
if (this.isFileSystem()) {
this.assertExistsAndIsDirectory();
List<File> fileList = Lists.newArrayList();
this.recursivelyAddFilesToList(this.rootDirectory, fileList);
return this.toTextFileList(fileList);
} else {
return FluentIterable.from(toIterable(this.zipFile.entries())).filter(new Predicate<ZipEntry>() {
public boolean apply(ZipEntry jarEntry) {
return !jarEntry.isDirectory() && jarEntry.getName().startsWith(ClasspathFileSource.this.path);
}
}).transform(new Function<ZipEntry, TextFile>() {
public TextFile apply(ZipEntry jarEntry) {
return new TextFile(ClasspathFileSource.this.getUriFor(jarEntry));
}
}).toList();
}
}
it will recursively add file which is absolutely started with the path. but when you run with java -jar, the jarEntry.getName is started with 'BOOT-INF'. one of the solution is that override the method with a subclass extend ClasspathFileSource, and modify the match rule. it will fix

JavaFx MediaPlayer behaves differently in unit test vs application, why?

I want to load meta data from an MP3 file, to be played by a JavaFx MediaPlayer. This works fine in the unit test, but not in the application. In the unit test, 6 items of metaData reported, but zero in the application. The method that "does the work" is the same.
The main class of the application extends Application. The test class extends ApplicationTest from TestFx. Could that affect the behavior?
The application:
public class MediaMain extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Map<String, Object> meta = metaData();
System.out.printf("Number of meta data: %d.%n", meta.size());
System.out.println(meta);
}
Map<String, Object> metaData() {
File audioFile = new File("src/main/resources", "beingBoiled.mp3");
final URI uri = audioFile.toURI();
final String source = uri.toString();
Media media = new Media(source);
new MediaPlayer(media);
return media.getMetadata();
}
}
The unit test:
class MediaMainTest extends ApplicationTest {
#Test
void testMeta() {
MediaMain main = new MediaMain();
Map<String, Object> metaData = main.metaData();
assertNotEquals(0, metaData.size());
System.out.printf("Number of meta data: %d.%n", metaData.size());
System.out.println(metaData);
}
}
Printout from the application:
Number of meta data: 0.
{}
Printout from the unit test:
Number of meta data: 6.
{year=1980, artist=The Human League, raw metadata={ID3=java.nio.HeapByteBufferR[pos=254 lim=3214 cap=3214]}, album=Travelogue, genre=(52), title=Being Boiled}
What could be the reason? It's a mystery to me. Written with Java 11, JavaFx 11.0.2 and TestFx 4.0.15-alpha.
You are referencing a file with a location of src/main/resources, this is probably not a good idea as your deployed application likely won't have a src/main/resources directory, plus the resource might be bundled within the application jar rather than as a file on disk, so using a file protocol to access it won't work.
It is probably best to use something like below:
String mediaLoc = getClass().getResource("/beingBoiled.mp3").toExternalForm()
Media media = new Media(mediaLoc)
Like in How load css file in javafx8. The exact location of the resource to be loaded may differ based on build and project structure. If you don't want to load from the class path, but instead via a File or over network http call, then you would need to use something else.
The above code assumes that your build system is setup to copy the media from the src/main/resources to your target packaging location and package the resource into the application distributable (e.g. an application jar file) in the root of the jar file.
Make sure that your build system is actually copying the file to the target location. You can check if it is there by running your build, looking at the resultant jar and running jar tvf <myjarfilename>.jar to see if the mp3 resource is in the correct location at the root of the jar file.

Accessing File from ClassPath

In my Maven project:
src/main/java/App --> has Main
src/main/resources/file.json
.
public class App
{
public static void main( String[] args )
{
URL url = App.class.getClass().getResource("/file.json");
File file = new File(url.getPath());
As I understand these Maven docs, I should be able to access file.json as it (should be) on the classpath since it's located at src/main/resources.
But, I'm getting a NullPointerException on the url.getPath() call.
You are doing App.class.getClass() which is going to get the root classloader (java.lang.Class's classloader), which isn't the same as your application classloader. You want to do App.class.getResource() instead.

How to add a line in all java files in eclipse

I am not sure if that is possible but I have a old java application projects which have 1000+ java files. I am trying to add log4j support to the application which require me to add
public static Logger logger = Logger.getLogger(MyClass.class.getName());
in every file.
Is there any way I can perform the operation using eclipse. I have tried source->format but that is not allowing me to add the line. Do I have to open every file and add that line?
You could make use of templates in eclipse, but in this case, you need to edit each file and add it.
Update :
Save following content in some file-named with extension ".xml"
<?xml version="1.0" encoding="UTF-8" standalone="no"?><templates><template autoinsert="true" context="java-members" deleted="false" description="adds the logger statement" enabled="true" name="logger">public static Logger logger = Logger.getLogger(${enclosing_type}.class.getName());</template></templates>
Press CTRL+3, Type - "templates" and choose for Templates- Java Editor as shown below
Import the file from menu from right as shown below
now go to any of your file and type "logger"in your class file and do CTRL+space , quick assist will show you the "logger" template
as shown below
and your logging statement will appear, with your class in which you are editing as shown below
You can do it programatically. Start with a filter for all your .java:
public class FileExtensionFilter implements FilenameFilter {
private Set<String> filteredExtensions;
public FileExtensionFilter() {
filteredExtensions = new HashSet<String>();
}
#Override
public boolean accept(File dir, String name) {
boolean accept = true;
for (String filteredExtension:filteredExtensions) {
accept = accept && !name.endsWith(filteredExtension);
}
return accept;
}
public void addFilteredExtension(String extension) {
filteredExtensions.add(extension);
}
}
Then you can look for the file using a recursive method:
public Set<String> searchFileBasedOnExtension(File file) {
Set<String> extensions = new HashSet<String>();
if (file.isDirectory()) {
for (File f : file.listFiles(fileExtensionFilter)) {
extensions.addAll(checkForExtensions(f));
}
} else {
String extension = file.getName().substring(Math.max(file.getName().lastIndexOf('.'),0));
extensions.add(extension);
fileExtensionFilter.addFilteredExtension(extension);
}
return extensions;
}
Then based on the set you receive, you can iterate it, read the file to find the position to add the "import" and also find the class name, and save it into a variable to replace it for each file, since each file represents a different class.
Sample:
for (String s : setWithFileNames) {
// Use BufferedReader to read the file, save the content in a String, then look inside the String the classname and the first import position.
// Use bufferedWriter to re-write the file with the changes you made.
}
Hope it gives you a hand with your requirement. Best regards.
Opening each file and adding this line would be tedious.
I am not sure if Eclipse has such thing.
But I would suggest to go for a shell script or a Java function to do this.
Read each file.
Search for the first '{' character.
Insert the logger statement in the line next to that.
You can get the class name from the file name.
I know this might not be the best solution for you.
Hope this helps.
If you have notepad ++ you can do it. Use the find replace feature for a direcory using regular expressions.
so a line starting with public class need to be replaced by the line and another line with the log statement.
Another suggestion is to use AspectJ. AspectJ is an extension to Java that allows you to systematically weave in extra functionality to existing classes. You would first need to install AJDT (AspectJ development tools). Then you need to create an Aspect like this:
aspect LoggingAspect {
before (Object thiz) : execution(public * *(..)) && this(thiz) {
Logger logger = Logger.getLogger(thiz.getClass().getName());
logger.log("Something");
}
}
The aspect above will log every execution of a public method of one of the classes that you compile. You can certainly tweak this in many ways. Logging is one of the simplest things that AspectJ can do. The nice thing about going down this path is that you can easily enable/disable logging from your project by commenting out 4 lines.
The main AspectJ website. And the AspectJ programming guide is a good place to start with AspectJ.
You can run the below command to add any line on the specific line number, Just provide the folder name it will search all the subfolders with the file extension as .java and add the line on the specific position:
find <Folder Path> -name "*.java" -exec sed -i '1i<Text: You want to add>' {} \;

How can I verifiy signed JARs with pure Java?

I don't want to use the jarsigner -verify. Is there no JAR util package for my problem?
I just want to verfiy a JAR in pure Java.
The "jarsigner" is just a small wrapper for a java program that verifies the jar. Inside your JDK there is a "tools.jar" (usally "C:\programs\Java\jdk1.6.0_13\lib\tools.jar" or something like this). Inside this library there is a class "JarSigner" that provides the desired ability. Just put the "tools.jar" on your classpath!
Heres an example program to demonstrate the behaviour
import sun.security.tools.JarSigner;
public class TestJarSigner {
public static void main(String[] args) {
JarSigner signer = new JarSigner();
signer.run(new String[] { "-verify", "tools.jar" });
}
}
Output is:
jar is unsigned. (signatures missing or not parsable)
The sources are availible if you need a deeper understanding of the signing process.

Categories

Resources