I am following the book Thinking in Java (4th edition), but I am getting an exception when trying on of the examples.
Main class:
enum Explore { HERE, THERE }
public class Reflection {
public static Set<String> analyze(Class<?> enumClass) {
print("----- Analyzing " + enumClass + " -----");
print("Interfaces:");
for(Type t : enumClass.getGenericInterfaces())
print(t);
print("Base: " + enumClass.getSuperclass());
print("Methods: ");
Set<String> methods = new TreeSet<String>();
for(Method m : enumClass.getMethods())
methods.add(m.getName());
print(methods);
return methods;
}
public static void main(String[] args) {
Set<String> exploreMethods = analyze(Explore.class);
Set<String> enumMethods = analyze(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(exploreMethods);
OSExecute.command("javap Explore.class ");
}
}
OSExecute.java:
package net.mindview.util;
import java.io.*;
public class OSExecute {
public static void command(String command) {
boolean err = false;
try {
Process process =
new ProcessBuilder(command.split(" ")).start();
BufferedReader results = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String s;
while((s = results.readLine())!= null)
System.out.println(s);
BufferedReader errors = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
// Report errors and return nonzero value
// to calling process if there are problems:
while((s = errors.readLine())!= null) {
System.err.println(s);
err = true;
}
} catch(Exception e) {
// Compensate for Windows 2000, which throws an
// exception for the default command line:
if(!command.startsWith("CMD /C"))
command("CMD /C " + command);
else
throw new RuntimeException(e);
}
if(err)
//Here it throws the exception:
throw new OSExecuteException("Errors executing " +
command);
}
}
Output:
----- Analyzing class Explore -----
Interfaces
Base: class java.lang.Enum
Methods:
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
----- Analyzing class java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interface java.io.Serializable
Base: class java.lang.Object
Methods:
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum)? true
Explore.removeAll(Enum): [values]
Error: cannot find class Explore.class
Exception in thread "main" net.mindview.util.OSExecuteException:
at net.mindview.util.OSExecute.command(OSExecute.java:35)
at Reflection.main(Reflection.java:33)**
The command javap cannot find the class Explore. Is this class in the default package? You should try to get javap Explore.class to run on the command line (probably fixing classpath or package), it has nothing to do with your code. –-- Philipp Wendler
OSExecute.command("javap D:/eclipse_workspace/thinking/bin/Explore.class ");
Related
I want compile Java program by making a Javac command in cmd using another Java program, then run it. How do I do that? Is there a class that i can use?
for example here is the cmd
C:\Users\UserName\Documents> Javac HelloWorld.java
How can i compile HelloWorld.java inside a java program, then run it.
Here is my initial source code wherein there is a directory and a Java file.
public class Test {
public static void main(String[] args) {
String directory = "C:\\Users\\UserName\\Documents";
String fileName = "HelloWorld.java";
}
}
Try this
try {
// Execute command
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);
// Get output stream to write from it
OutputStream out = child.getOutputStream();
out.write("<execute the java class by mentioning the usual command>");
out.flush();
out.close();
} catch (IOException e) {
}
You probably want to compile the other source code first. The Java compiler is actually written in Java itself. You do not need to invoke the javac.exe, instead take a look at javax.tools.ToolProvider.getSystemJavaCompiler() ToolProvider Javadoc.
Once you compiled the source code file with that, you can use the class loader to load the compiler class file and invoke the code from there, probably by means of reflection.
Overall you are asking for an advanced use case.
if you want to compile different java files using this a program , you can try this method.
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac YourDir/HelloWorld.java");
runProcess("java YourDir.HelloWorld");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class HelloWorld {
public static void main(String[] args) {
System.out.println("ok");
}
}
(Sorry for my english I'm french) I'm creating a tiny Java IDE for my school project, but I'm facing a problem with running classes under Linux (I'm using Debian 7.3), no problem with Win 8.1
I'm using ProcessBuilder class to execute the java bin with some arguments, wich are args and projectOut
args = the class we want to run
projectOut = the absolute project path+"/out"
package com.esgi.honeycode;
import java.io.*;
import java.util.Scanner;
public class CustomRun {
public static void run(String args, final String projectOut) throws IOException {
System.out.flush();
if (args != null && projectOut != null) {
//SEPARATOR is a const for the file separator
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", "\"" + System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out\"", args);
System.out.println(builder.command());
builder.redirectErrorStream(true);
final Process process = builder.start();
Thread outThread = new Thread()
{
#Override
public void run() {
try {
String line;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
Thread inThread = new Thread() {
#Override
public void run() {
Scanner s = new Scanner(System.in);
//Need to control in before !!
while (true) {
String input = s.nextLine();
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(process.getOutputStream()))) {
pw.write(input);
pw.flush();
}
}
}
};
outThread.start();
inThread.start();
}
}
}
Testing with a simple class :
public class MyClass{
public static void main(String[] args)
{
System.out.println("TESTESTE");
}
}
the class is stored in : /home/m3te0r/HoneyCodeProjects/untitledaaa/out
And if I try to run the class, I get this output, with the command print :
[java, -classpath, "/home/m3te0r/Bureau/HoneyCode.jar:/home/m3te0r/HoneyCodeProjects/untitledaaa/out", MyClass]
Error: Could not find or load main class MyClass
Like I said, there is no problem under Win 8.1 and it also works when I run the same command in a terminal.
EDIT FOR THE ANSWER ():
Ok, so I figured out what was wrong.
I just removed the escaped double quotes fot the classpath and it worked.
I was thinking there would be a problem with spaced dir names or files, but there is not.
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out", args);
I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I wanted to consolidate two functions.
After getting a viable solution, I decided to play with the code a bit further, and came up with this:
package hu.flux.helper;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import javax.servlet.jsp.JspWriter;
import com.objectmentor.library.web.framework.mocks.*;
// A holder for formatting data
public class NameAndAddress
{
public String firstName;
public String middleName;
public String lastName;
public String address1;
public String address2;
public String city;
public String state;
public String zip;
public String FormattedString()
{
String formattedString = "<PRE>\n" + firstName;
// Add the middle name only if it contains data.
if ((middleName != null) && (middleName.length() > 0))
{formattedString += " " + middleName;}
formattedString += " " + lastName + "\n";
formattedString += address1 + "\n";
if ((address2 != null) && (address2.length() > 0))
formattedString += address2 + "\n";
formattedString += city + ", " + state + " " + zip + "\n</PRE>";
return formattedString;
}
// Print out the name and address.
public void print(Writer writer) {
long now = System.currentTimeMillis();
System.out.println("--Entering-- " + now);
PrintWriter p = new PrintWriter (writer);
p.write(this.FormattedString());
now = System.currentTimeMillis();
System.out.println("--Exiting-- " + now);
}
/*
public void print(JspWriter out) throws java.io.IOException
{ print (new PrintWriter(out)); }
*/
#SuppressWarnings("deprecation")
public static void main (String args[])
{
NameAndAddress naa = new NameAndAddress();
naa.firstName = "Brian";
naa.middleName = "Matthew";
naa.lastName = "Kessler";
naa.address1 = "Tatra u. 15/b V/3";
naa.city = "Budapest";
naa.state = "Hungary";
naa.zip = "HU-1136";
System.out.println("\nTesting PrintWriter...");
PrintWriter p = null;
try { p = new PrintWriter("d:/temp/pwriter_text.txt"); }
catch (FileNotFoundException e)
{
System.err.print ("Can not create new PrintWriter: " + e);
e.printStackTrace();
}
naa.print(p);
p.flush();
FileInputStream fis;
DataInputStream dis;
try
{
fis = new FileInputStream("d:/temp/pwriter_text.txt");
dis = new DataInputStream (fis);
while (dis.available() != 0)
{ System.out.println(dis.readLine()); }
dis.close();
}
catch (Exception e)
{
System.err.println("File input error");
}
System.out.println("\nTested PrintWriter...");
System.out.println("---------------------");
System.out.println("\nTesting JSPWriter...");
JspWriter j = null;
naa.print(j);
System.out.print("\nTested JSPWriter...");
System.out.println("---------------------");
System.out.println("\nTesting MockJspWriter");
MockJspWriter m = null;
m = new MockJspWriter(255, true);
naa.print(m);
System.out.print(m.getContent());
System.out.println("\nTested MockJSPWriter...");
System.out.println("---------------------");
}
}
I expected that the print() method would catch both JspWriter and PrintWriter.
While this solution worked fine for PrintWriter, when I tried to run this as a console application, I get this output:
Testing PrintWriter...
--Entering--
--Exiting--
<PRE>
Brian Matthew Kessler
Tatra u. 15/b V/3
Budapest, Hungary HU-1136
</PRE>
Tested PrintWriter...
---------------------
Testing JSPWriter...
--Entering--
Exception in thread "main" java.lang.NullPointerException
at hu.flux.helper.NameAndAddress.print(NameAndAddress.java:46)
at hu.flux.helper.NameAndAddress.main(NameAndAddress.java:101)
I get a different error, however, if I try to access print(Writer writer) from a JSP:
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:492)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:407)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
javax.servlet.ServletException: java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:898)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:827)
org.apache.jsp.Address_jsp._jspService(Address_jsp.java:92)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
java.lang.NoSuchMethodError: hu.flux.helper.NameAndAddress.print(Ljavax/servlet/jsp/JspWriter;)V
org.apache.jsp.Address_jsp._jspService(Address_jsp.java:81)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.2 logs.
Apache Tomcat/7.0.2
When calling from the JSP, I can make a call to the class with JspWriter work by adding this code:
public void print(JspWriter out) throws java.io.IOException
{ print (new PrintWriter(out)); }
However, when attempting to use JspWriter from a console application (for testing -- I don't think anyone would ever need to use JspWriter in the console!), the above console error is moved to this function.
If print(JspWriter out) can fix the problem for JSPs, shouldn't it also fix the problem for console apps?
Moreover, if JspWriter is a Writer object, shouldn't it always be a Writer object, regardless whether it is called from the console or a JSP?
This exception says that your JSP code haven't been recompiled after you changed print(JspWriter) to print(Object), so it still tries to call print(JspWriter) and can't find it.
In order to force a recompilation you may modify your JSP page.
This is because the Java compiler tries to find the PrintWriter.print method on the JspWriter object. Although it has a print method, this method does not match because it is from another class. Java does not support duck-typing and goes to great lengths to prevent it.
It is also considered bad practice to use exceptions in programming logic.
You'll have to do sthg like
try
{
if (out instanceof PrintWriter) {
((PrintWriter) out).print(this.formattedString());
} else if (out instanceof JspWriter) {
((JspWriter) out).print(this.formattedString());
} else {
throw new IllegalArgumentException("NameAndAddress.print expected ether a PrintWriter or a JspWriter but received a " + out.getClass().getName());
}
catch (Exception ex)
{ System.err.println("\"out\" is not a printable type: " + ex); }
BTW: methods in Java should start with a lowercase letter by convention.
What you posted should work since both PrintWriter and JspWriter are subclasses of Writer (and of course both are subclasses of Object). Something seems to be wrong either with your test code or with your environment.
Maybe you can try a simplified example and see if that works, then build up from there. I can suggest starting here:
public class Test
{
public void print(Writer writer) throws IOException
{
if (writer == null)
System.out.println("Null writer");
else
{
writer.write("hello");
writer.flush();
}
}
public static void main(String args[]) throws IOException
{
Test test = new Test();
System.out.print("Testing PrintWriter...");
PrintWriter p = new PrintWriter("d:/temp/pwriter_text.txt");
test.print(p);
System.out.print("Tested PrintWriter...");
System.out.print("Testing JspWriter...");
JspWriter j = null;
test.print(j);
System.out.print("Tested JspWriter...");
}
}
This should compile and run. The second time test.print() is called, the JspWriter being passed in will be null, but you should not get any NoSuchMethodError. If this works, take the code and test it from your servlet / JSP pages. Hopefully this will help you find the problem.
JspWriter is not a PrintWriter
you can wrap the original writer inside a print writer like this:
if (out instance of Writer) {
PrintWriter p = new PrintWriter((Writer) out));
p.print...
}
Well you start your method by casting to a PrintWriter, so maybe the jvm optimized the method for you. Since JspWriter does not subclass from PrintWriter, your best bet is to write two methods:
public void print(JspWriter out)
{
if (out == null) return;
try {
out.print(this.FormattedString());
} Except (IOException e) {
// handle error
}
}
public void print(PrintWriter out)
{
if (out == null) return;
try {
out.print(this.FormattedString());
} Except (IOException e) {
// handle error
}
}
If only JspWriter and PrintWriter had a common interface... sigh.
Your print() casts Object to a PrintWriter. But when you pass in a JspWriter which isn't PrintWriter, the cast fails.
However, PrintWriter and JspWriter are both descended from Writer. Can you change your print() method to accept a Writer instead of an Object, and then use the Writer.write() method within print()? This is common to both classes.
This:
public void print(Writer writer) {
try {
writer.write(this.FormattedString());
} catch (IOException e) {
// log something...
}
}