ColdFusion: about using custom "own written" Java classes - java

I need to use my own java class in a cfml page.
This entry in the documentation sounds great but does not explain which files I have to create.
I tried to create a test.cfm page under my website root. Then placed TestClass.java + TestClass.class in the same path. But that results in an error "class not found"!.
Can you please help me?

a TestClass.java + TestClass.class in the same path.
You cannot just place .class files anywhere. When the CF server starts, it only checks specific locations for classes/jars. Those locations are referred to as the "CF class path". Your compiled .class file must be placed within the CF class path, or it will not be detected.
To use a custom java class:
Create a source file ie YourTestClass.java
Compile the source code into a class file ie YourTestClass.class
Place the compiled .class file somewhere within the CF classpath, such as:
WEB-INF\classes - for individual .class files
WEB-INF\lib - for .jar files (multiple classes)
Note: You could also add the item to the CF class path via the ColdFusion Administrator. However, placing the class in one of the default directories is simpler.
Restart the ColdFusion server so it detects the new classes
Note: Though you can use individual .class files, it is more common to package them into .jar files.

Related

Getting resource file from inside jar

I need to get a resource from inside the root of the application when its packed into jar. My project is like this:
ProjectRoot
resource.txt //want to access from here
src
main
java
package1
package2
package3
Main.java
target
app.jar
classes
resource.txt //works when here
package1
package2
package3
Main.class
I use this code:
Path path = Paths.get("resource.txt");
When run before packaging into a jar, it finds the file just fine (inside ProjectRoot). When running the jar, it can't find it, and transforms this path to target/resource.txt.
This code:
BufferedReader br = new BufferedReader(new InputStreamReader(new Main().getClass().getClassLoader().getResourceAsStream(
"resource.txt")));
when run before packaging looks for the resource inside target/classes. After packaging it claims to taking the resource from .../target/app.jar!/resource.txt.
This code:
BufferedReader br = new BufferedReader(new InputStreamReader(new Main().getClass().getClassLoader().getResourceAsStream(
"/resource.txt")));
I can't understand where's looking for the resource, but it doesn't seem to be ProjectRoot.
All I want to do is to place the resource inside ProjectRoot and be able to access it from both outside jar (when running the class files from IDE) and inside (after having packaged the files into a jar file using Maven).
EDIT: I NEED THE CODE TO WORK BOTH FOR PRE- AND POST- packaging. MEANING: If I run a Main.java FROM INSIDE IDE IT WOULD GET THE RESOURCE; IF I PACKAGE EVERYTHING INTO JAR AND RUN JAR IT WOULD GET THE RESOURCE - ALL WITH THE SAME CODE.
Use: Main.class.getResource("/resource.txt").
Note that your attempt using any call to getClassLoader is strictly worse (it's more text, and will fail more often, because that class loader can in exotic cases be null (specifically, when you're part of the bootstrap loader), whereas calling getResource directly on the class always works.
The reason your snippet does not work is because when invoking getResource on the classloader, you must NOT start the resource with a slash. When invoking on a class directly, you can (if you don't, it'll be relative to the package of the class you're calling it on, if you do, it'll be relative to the root).
TL;DR: Of the forms SomeClass.class.getClassLoader().getResource, getClass().getResource and MyClass.class.getResource, only the last one is correct, the rest are strictly inferior and therefore should not be used at all.
Maven uses something called the Standard Directory Layout. If you don't follow this layout then the plugins can't do their job correctly. Technically, you can configure Maven to use different directories but 99.999% of the time this is not necessary.
One of the features of this layout is that production files go in:
<project-dir>/src/main/java
All *.java files
<project-dir>/src/main/resources
All non-*.java files (that are meant to be resources)
When you build your project the Java source files are compiled and the *.class files are put into the target/classes directory; this is done by the maven-compiler-plugin. Meanwhile, the resource files are copied from src/main/resources into target/classes as well; the maven-resources-plugin is responsible for this.
Note: See Introduction to the Build Lifecycle for more information about phases and which plugins are executed by which phase. This Stack Overflow question may also be useful.
When you launch your application from the IDE (possibly via the exec-maven-plugin) the target/classes directory is put on the classpath. This means all the compiled classes from src/main/java and all the copied resources from src/main/resources are available to use via the classpath.
Then, when you package your application in a JAR file, all the files in target/classes are added to the resulting JAR file (handled by the maven-jar-plugin). This includes the resources copied from src/main/resources. When you launch the application using this JAR file the resources are still available to use via the classpath, because they're embedded in the JAR file.
To make resource.txt available on the classpath, just move:
<project-dir>/resource.txt
To:
<project-dir>/src/main/resources/resource.txt.
Then you can use Class#getResource with /resource.txt as the path and everything should work out for you. The URL returned by getResource will be different depending on if you're executing against target/classes or against the JAR file.
When executing against target/classes you'll get something like:
file:///.../<project-dir>/target/classes/resource.txt
When executing against the JAR file you'll get something like:
jar:file:///.../<project-dir>/target/projectname-version.jar!/resource.txt
Note: This all assumes resource.txt is actually supposed to be a resource and not an external file. Resources are typically read-only once deployed in a JAR file; if you need a writable file then it's up to you to use a designated location for the file (e.g. a folder in the user's home directory). One typically accesses external files via either java.io.File or java.nio.file.*. Remember, resources are not the same thing as normal files.
Now, if you were to put resource.txt directly under <project-dir> that would mean nothing to Maven. It would not be copied to target/classes or end up in the JAR file which means the resource is never available on the classpath. So just to reiterate, all resources go under src/main/resources.
Check out the Javadoc of java.lang.Class#getResource(String) for more information about the path, such as when to use a leading / and when not to. The link points to the Javadoc for Java 12 which includes information about resources and modules (JPMS/Jigsaw modules, not Maven modules); if you aren't using modules you can ignore that part of the documentation.

How to add a class to classpath to not get import errors in Java [duplicate]

I have two classes:
MyApplication Library
The Library has already been compiled into Library.class and the source code is no longer available. I am now trying to compile MyApplication from source. MyApplication depends on the Library. The Library has a package name of org.myCompany. I tried setting my classpath to the following:
set CLASSPATH=C:\java\project\org\myCompany\Library.class;.
which produced the following javac compiler error message:
MyApplication.java:33: cannot find symbol
symbol: class Library
location: class MyApplication
Library theLibrary = new Library();
So I changed my classpath to be:
set CLASSPATH=C:\java\project\;.
which produced the exact same error message.
How do I set my Windows classpath to include the Library.class file? Should it point at the folder contains the org\myCompany subfolders? Or point directly to the class file? Or to the folder containing the class file (even though the class is in a package and belongs in a subfolder)?
I do an echo %CLASSPATH% after my set command and the classpath is being set correctly. I also made an ant build.xml file and encountered the same problem. In fact, ant -verbose confirmed that my classpath is being set correctly.
First of all: the use of the CLASSPATH environment variable is very strongly discouraged. The best thing is for you to forget that it exists. Use the -cp command line switch or similar methods to set the classpath.
Second, the classpath entries each represent a place where the classloader will start looking for .class according to the package hierarchy, i.e. it will look for the class org.myCompany.Library in a subfolder org/myCompany in any of the classpath entries.
Therefore, if
you add a classpath entry C:\java\project\
and there is a class file C:\java\project\org\myCompany\Library.class
which is actually part of a package org.myCompany (capitalization matters here!)
and your MyApplication class has an import org.myCompany.Library;
Then it really should work.
You cannot add a single class in your classpath like this. You have 3 solutions:
add this class in the path of your other compiled classes (respecting the package naming of your directories)
add the root directory of this class in your classpath (in your case "C:\java\project\")
add this single class into a jar and add this jar to the classpath
For your problem, the thrird choice is cleaner: external dependencies normally are packaged into jar files.
If your .class file isn't in jar file, point your classpath to the parent dir where package of class resides, e.g., for class org.myCompany.Library, point your CP to directory containing org/myCompany.
If your .class file included into some jar file, add full path to that jar to your classpath.
If you compiled the class files to a different directory, the classpath needs to point to where the .class file is.
set CLASSPATH=C:\java\project\;
is correct assuming that that the class file is in the same directory as the .java source file.
Is there a problem locating the Library to the same root project where is your MyApplication class
Example, if:
c:/project/org/company/MyApplication.class
Can you locate the Library class into:
C:/project/org/myCompany/Library.class
please notice, that the folders org/myCompany and org/company are located under the same folder c:/project/.
Please notices that this solution works for you if the Library Class is only used by your application.
Edited
Windows command prompt is tedious, after setting the classpath please close and re-open the Command Prompt, so it can see the new classpath's value.
For the classpath to work, you need to have a folder structure which matches the package hierarchy. So if your class is org.myCompany.Library, you must create a nested folder structure of C:\java\project\org\myCompany and place your Library class file in the myCompany folder. Then set the class path to C:\java\project\

Factual API and coldfusion

I took the java implementation of the Factual API (reference http://developer.factual.com/) and made a JAR file for factual. I did this by opening a new project in eclipse with the factual java files and then exporting to a new jar file.
I put that jar file in my coldfusion installation's /WEB-INF/lib/ folder.
After restarting Coldfusion, I tried to create a new cfobject like so
<cfscript>
// Initialize the Java class.
factualClass=CreateObject("java", "src.main.java.com.factual.driver.Factual");
</cfscript>
I get an error indicating that it cannot find the Factual class.
Can anybody give me some guidance?
(Summary from comments)
It sounds like you may be exporting the source files ie *.java rather than the compiled class files, ie *.class. In the Jar Export wizard, be sure to select the "Export generated class files and resources" option. (To automatically compile the project sources before expi, enable the setting: JAR packaging > Build projects if not build automatically option). If you prefer you can also find pre-compiled jars in the MVN repository.
put that jar file in my coldfusion installation's /WEB-INF/lib/
folder.
CF10+ also supports dynamic class loading via a new application level setting THIS.javaSettings.
// Initialize the Java class.
factualClass=CreateObject("java", "src.main.java.com.factual.driver.Factual");
Just as a point of interest, src/main/java/ is not actually part of the libary class name. It is a standard directory structure used in Maven projects. It is probably included when exporting the sources, but not the compiled classes.
You can always verify the correct path and class name either by examining the API ie javadocs or by viewing one the source files. Package declarations are always at the top of the source file, such as on line 1 of src/main/java/com/factual/driver/Factual.java:
package com.factual.driver; // ie "com.factual.driver"
.. and the class declaration on line 39.
public class Factual { // ie "Factual"
Combined that gives you the exact (case-sensitive) path to use with createObject:
factualClass=CreateObject("java", "com.factual.driver.Factual");

Add a new class to an existing JAR File(which contains source code)

I'll try to illustrate the problem as simple as I can.
I have a JAR file, which I extracted using Winrar. (The jar file contains an open source android library).
I want to modify this JAR file by adding a new class to the library.
So here are my steps:
First, I created a class using Eclipse and set the package name same as the android's library package name.
Second, I copied this java File to the folder of the other java files in the library.
Third, I tried to compile the JAVA file via the CMD using javac.
The path of the new java file and the other .JAVA and .CLASS files of the library is: C:\com\example\core\
The name of the new java file would be: "MyNewClass.java"
The command I run via the CMD is: javac C:\com\example\core\MyNewClass.java
But, during the compilation I get many errors saying: Cannot find symbols.
I've been looking up for a solution of this problem but couldn't figure how to solve it and make the new JAR File having another class that I created seperately.
What am I missing?
As per earlier comments:
Rather than trying to modify the JAR, you can get access to the full source code of the Universal Image Loader library by cloning the repository using git or hitting "Download ZIP" on the righthand side of the page you linked.
Once you have the source, import the library in your IDE. From there on you'll be able to build the whole thing from scratch, make any adjustments/modifications you like, etc.
Your classpath might be wrong or there might be some mistake in package name.
When a Java program is being compiled the compiler it creates a list of all the identifiers in use. If it can't find what an identifier refers to it cannot complete the compilation. This is what the cannot find symbol error message is saying, it doesn't have enough information to piece together what the Java code wants to execute.
Try:
javac -cp com/* C:\com\example\core\MyNewClass.java
That should make the compiler aware of all the other classes under com/...

How to get current path when program is loaded dynamically

I'm not able to give this question an apt title so apology for that.
I am making a modularised application. I load various jar files at runtime and invoke particular method of a particular class (of the jar file) at run time.
The jar file has some supported file. Now my jar file uses another application , lets say abc which is located in the same directory where i have kept the jar file. When i run the jar file then
new File(".").getAbsolutePath()
gives the correct path (this is where abc is located) and program runs fine. But when i load this jar file dynamically and invoke method using reflection above code gives the path of the parent program and abc is not found at that path.
Now my question is how do i find the path in which my jar file exists when i'm running my jar file's code using reflection.
Please let me know if you need more explanation.
Try something like this:
public static void main(String[] args) {
System.out.println(StringUtils.class.getResource("StringUtils.class"));
}
(Note: StringUtils is present on my classpath as a Maven dependency at the time) This gives me:
jar:file:/home/******/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar!/org/apache/commons/lang3/StringUtils.class
Since the class is in a JAR file, it also gives me the location of the class file within the JAR.

Categories

Resources