How can I get the current stack trace in Java? - stack-trace

How do I get the current stack trace in Java, like how in .NET you can do Environment.StackTrace?
I found Thread.dumpStack() but it is not what I want - I want to get the stack trace back, not print it out.

You can use Thread.currentThread().getStackTrace().
That returns an array of StackTraceElements that represent the current stack trace of a program.

StackTraceElement[] st = Thread.currentThread().getStackTrace();
is fine if you don't care what the first element of the stack is.
StackTraceElement[] st = new Throwable().getStackTrace();
will have a defined position for your current method, if that matters.

for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste + "\n");
}

Thread.currentThread().getStackTrace();
is available since JDK1.5.
For an older version, you can redirect exception.printStackTrace() to a StringWriter() :
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

Tony, as a comment to the accepted answer, has given what seems to be the best answer which actually answers the OP's question:
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
... the OP did NOT ask how to get a String from the stack trace from an Exception. And although I'm a huge fan of Apache Commons, when there is something as simple as the above there is no logical reason to use an outside library.

You can use Apache's commons for that:
String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);

On android a far easier way is to use this:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);

Another solution (only 35 31 characters):
new Exception().printStackTrace();
new Error().printStackTrace();

To get the stack trace of all threads you can either use the jstack utility, JConsole or send a kill -quit signal (on a Posix operating system).
However, if you want to do this programmatically you could try using ThreadMXBean:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) {
StackTraceElement[] elems = info.getStackTrace();
// Print out elements, etc.
}
As mentioned, if you only want the stack trace of the current thread it's a lot easier - Just use Thread.currentThread().getStackTrace();

I suggest that
Thread.dumpStack()
is an easier way and has the advantage of not actually constructing an exception or throwable when there may not be a problem at all, and is considerably more to the point.

Silly me, it's Thread.currentThread().getStackTrace();

In Java 9 there is a new way:
public static void showTrace() {
List<StackFrame> frames =
StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )
.walk( stream -> stream.collect( Collectors.toList() ) );
for ( StackFrame stackFrame : frames )
System.out.println( stackFrame );
}

Getting stacktrace:
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Printing stacktrace (JAVA 8+):
Arrays.asList(ste).forEach(System.out::println);
Printing stacktrage (JAVA 7):
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : ste) {
sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);

To string with guava:
Throwables.getStackTraceAsString(new Throwable())

I have a utility method that returns a string with the stacktrace:
static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}
And just logit like...
...
catch (FileNotFoundException e) {
logger.config(getStackTrace(e));
}

try {
}
catch(Exception e) {
StackTraceElement[] traceElements = e.getStackTrace();
//...
}
or
Thread.currentThread().getStackTrace()

Maybe you could try this:
catch(Exception e)
{
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
String errorDetail = writer.toString();
}
The string 'errorDetail' contains the stacktrace.

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
loop through StackTraceElement and get your desired result.
for (StackTraceElement ste : stackTraceElements )
{
//do your stuff here...
}

You can use jstack utility if you want to check the current call stack of your process.
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id#]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message

I used answers from above and added formatting
public final class DebugUtil {
private static final String SEPARATOR = "\n";
private DebugUtil() {
}
public static String formatStackTrace(StackTraceElement[] stackTrace) {
StringBuilder buffer = new StringBuilder();
for (StackTraceElement element : stackTrace) {
buffer.append(element).append(SEPARATOR);
}
return buffer.toString();
}
public static String formatCurrentStacktrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return formatStackTrace(stackTrace);
}
}

For people, who just want to get the current stacktrace to their logs, I would go with:
getLogger().debug("Message", new Throwable());
Cheers

You can also use exception to print stack instead of taking pain of putting new line char:
Exception e = new Exception();
e.setStackTrace(Thread.currentThread().getStackTrace());
loggr.info(e);

This is an old post, but here is my solution :
Thread.currentThread().dumpStack();
More info and more methods there :
http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html

Related

How to execute a PowerShell command from JavaFX

I have this Powershell command that I would like know how to execute from Java / JavaFx:
powershell.exe Get-WMIObject Get-WMIObject Win32_SerialPort | Select-Object Name,DeviceID,Description,Caption, PNPDeviceID,Status | Out-File -FilePath C:\\path\\to\\file\\test.txt
I've read and tried several examples I found online and in forums. But I'm still stuck! This is the JavaFx method I'm using:
public void PowerShellCommand() throws IOException
{
String command = "powershell.exe Get-WMIObject Get-WMIObject Win32_SerialPort | Select-Object Name,DeviceID,Description,Caption, PNPDeviceID,Status | Out-File -FilePath C:\\path\\to\\file\\test.txt";
Process powerShellProcess = Runtime.getRuntime().exec(command);
powerShellProcess.getOutputStream().close();
}
Executing the command directly in PowerShell produces the right results.
A .txt file with content is created. Like this one (which is correct):
Name : Kommunikationsanschluss (COM1)
Description : Kommunikationsanschluss
Caption : Kommunikationsanschluss (COM1)
PNPDeviceID : ACPI\PNP0501\1
Status : OK
(Goal is to fetch the various results out of the .txt file content and display them on a UI).
But using the code in the above method creates an empty .txt file. I'm certainly doing something wrong, and would need some help to fix it.
Do you have any ideas? Your time and help is very much appreciated!
AveJoe
PS: I'm using a Windows 10 Pro machine.
I believe you are actually asking several questions, including
How to execute powershell command from java?
How to read a file in java?
How to display contents of a text file in JavaFX GUI?
I will answer the first question.
(Indeed, I believe a post should contain a single question.)
The ProcessBuilder constructor takes an array of String. Each word in your command becomes a single element in the array. Words are separated by one or more space characters.
Also you need to read the Process output and error output. I recommend creating two separate threads - one for output and another for error. And since you can easily write the Process output to a file, there is no need to use Out-File in your powershell command.
Here is a java program to execute the powershell command from your question.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class ProcBldr {
public static void main(String[] args) {
ProcessBuilder procBldr = new ProcessBuilder("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"Get-WMIObject",
"Win32_SerialPort",
"|",
"Select-Object",
"Name,DeviceID,Description,Caption,PNPDeviceID,Status");
Process proc;
try {
proc = procBldr.start(); //throws java.io.IOException
Thread out = new Thread(new ProcOutput(proc.getInputStream(), new File("C:\\Users\\USER\\stdout00.txt")));
Thread err = new Thread(new ProcOutput(proc.getErrorStream(), new File("C:\\Users\\USER\\stderr00.txt")));
out.start();
err.start();
int exitCode = proc.waitFor(); //throws java.lang.InterruptedException
out.join();
err.join();
System.out.println("\nExited with error code : " + exitCode);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
class ProcOutput implements Runnable {
private BufferedReader buffReader;
private PrintWriter pw;
public ProcOutput(InputStream is, File f) throws IOException {
InputStreamReader isr = new InputStreamReader(is);
buffReader = new BufferedReader(isr);
pw = new PrintWriter(f);
}
public void run() {
try {
String line = buffReader.readLine();
while (line != null) {
pw.append(line);
pw.append(System.lineSeparator());
line = buffReader.readLine();
}
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
finally {
pw.close();
try {
buffReader.close();
}
catch (IOException xIo) {
// Ignore.
}
}
}
}
The output of the powershell command is written to file stdout00.txt. The file contains the following...
Name : Communications Port? (COM1)
DeviceID : COM1
Description : Communications Port
Caption : Communications Port? (COM1)
PNPDeviceID : ACPI\PNP0501\0
Status : OK
I recommend you read the article When Runtime.exec() won't. It is very old and was written before class ProcessBuilder was part of the JDK but it also applies to ProcessBuilder and therefore, in my opinion, still relevant to the latest JDK version (12.0.1 at time of writing this).
Note that my environment is Windows 10 (64 bit) and Oracle JDK 12.0.1 (also 64 bit)

How can I Print DOCX file in Netbeans using Aspose.words?

Recently, I was working on a project that can print DOCX files in Netbeans. I am new in java so I'm not really familiar with it. I use Aspose.Words but I really don't know how to use it. I watch many tutorials but they are not in NetBeans so I am confused. Thanks a lot in advance for helping me.
This is my code:
String dox = path.getText();
XWPFDocument docx = null;
try {
docx = new XWPFDocument(POIXMLDocument.openPackage(dox));
XWPFWordExtractor ext = new XWPFWordExtractor(docx);
content.setText(ext.getText());
} catch (IOException ex) {
Logger.getLogger(count.class.getName()).log(Level.SEVERE, null, ex);
}
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(new OutputPrinter(path.getText()));
boolean doPrint = job.printDialog();
if (doPrint)
{
try
{
job.print();
}
catch (PrinterException e)
{
// Print job did not complete.
}
}
I tried extracting it but it only gets the content. What I'm trying is to print the whole document just like in the MSWord.
First of all: Why is this a NetBeans question? I can’t see any NetBeans relations, maybe you should change it to Java (at least the tag).
Second: I think your question is a duplicate to this one

HAPI v2 after terser: get entire changed message

I have an HL7 message whose content I'm manipulating slightly with the terser.set() method. Once I've done that, I see in the debugger that it's been changed just how I want it, but I can't seem to get the whole message back intact. I've tried (for example):
HapiContext context = new DefaultHapiContext();
Parser parser = context.getGenericParser();
Message message = parser.parse( MESSAGE );
Terser terser = new Terser( message );
terser.set( "/PID-2", "XXX XX XXXX" );
String fixedMessage = message.encode();
...which gets me close, however, lines (segment lines) that ended in just vertical bars (pipes) with no values in their fields come back trimmed (the vertical bars are simply dropped). I want the message to remain identical to what I put in (if also modified where I did it on purpose).
I think you need to use addForcedEncode in the ParserConfiguration.
Like
#Test
public void testSetManualRepetitions() {
try {
String m = "MSH|^~\\&|hl7Integration|hl7Integration|||||ADT^A01|||2.3|\r" +
"EVN|A01|20130617154644\r" +
"PID|1|465 306 5961||407623|Wood^Patrick^^^MR||19700101|1||||||||||\r" +
"PV1|1||Location||||||||||||||||261938_6_201306171546|||||||||||||||||||||||||20130617134644|||||||||";
HapiContext hc = new DefaultHapiContext();
ExecutorService es = hc.getExecutorService(); // to avoid npe when closing context should be fixed https://sourceforge.net/p/hl7api/bugs/223/
ParserConfiguration pc = hc.getParserConfiguration();
PipeParser pipeParser = hc.getPipeParser();
Message message = pipeParser.parse(m);
Terser terser = new Terser(message);
//Add first Address
terser.set("/.PID-11(0)-1", "13 Oxford Road");
terser.set("/.PID-11(0)-3", "Oxford");
//Add second Address
terser.set("/.PID-11(1)-1", "16 London Road");
terser.set("/.PID-11(1)-3", "London");
pc.addForcedEncode("PID-26-1"); // make sure PID has 26 fields
System.out.println(message.encode().replaceAll("\r", "\r\n"));
hc.close();
} catch (HL7Exception e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
yields:
/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/bin/java -ea -Didea.launcher.port=7540 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA CE.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath "/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar:/Applications/IntelliJ IDEA CE.app/Contents/plugins/junit/lib/junit-rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/lib/tools.jar:/Users/thomas/git/Hapi-HL7-Terser/target/test-classes:/Users/thomas/.m2/repository/junit/junit/4.4/junit-4.4.jar:/Users/thomas/.m2/repository/ca/uhn/hapi/hapi-base/2.2/hapi-base-2.2.jar:/Users/thomas/.m2/repository/ca/uhn/hapi/hapi-structures-v21/2.2/hapi-structures-v21-2.2.jar:/Users/thomas/.m2/repository/ca/uhn/hapi/hapi-structures-v23/2.2/hapi-structures-v23-2.2.jar:/Users/thomas/.m2/repository/ca/uhn/hapi/hapi-structures-v24/2.2/hapi-structures-v24-2.2.jar:/Users/thomas/.m2/repository/ca/uhn/hapi/hapi-structures-v25/2.2/hapi-structures-v25-2.2.jar:/Users/thomas/.m2/repository/org/slf4j/slf4j-simple/1.6.0/slf4j-simple-1.6.0.jar:/Users/thomas/.m2/repository/org/slf4j/slf4j-api/1.6.0/slf4j-api-1.6.0.jar:/Users/thomas/.m2/repository/org/slf4j/log4j-over-slf4j/1.6.2/log4j-over-slf4j-1.6.2.jar" com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.hl7integration.hapi.tests.SetRepetitionsTerserTest,testSetManualRepetitions
68 [main] INFO ca.uhn.hl7v2.util.Home - hapi.home is set to /Users/thomas/git/Hapi-HL7-Terser/.
170 [main] INFO ca.uhn.hl7v2.VersionLogger - HAPI version is: 2.2
197 [main] INFO ca.uhn.hl7v2.VersionLogger - Default Structure libraries found for HL7 versions 2.1, 2.3, 2.4, 2.5,
MSH|^~\&|hl7Integration|hl7Integration|||||ADT^A01|||2.3
EVN|A01|20130617154644
PID|1|465 306 5961||407623|Wood^Patrick^^^MR||19700101|1|||13 Oxford Road^^Oxford~16 London Road^^London|||||||||||||||
PV1|1||Location||||||||||||||||261938_6_201306171546|||||||||||||||||||||||||20130617134644
Technically you are not changing the message, you parse it to a Java object and encode it back to string. So that your output message looks like your input message. There could still be subtle differences afterwards (e.g. if your input message is dynamic).
From the docs (http://hl7api.sourceforge.net/configuring_hapi.html):
Forced Encoding
By default, when encoding a message HAPI will not encode any segments or fields that have no content and therefore have no semantic meaning in the message.
This can cause problems if you need to transmit a message to a system that expects certain empty content to be present in order to get "hints" about where in the message it is.
The addForcedEncode method may be used to add Terser paths which should be forced to be encoded:
parser.getParserConfiguration().addForcedEncode("PATIENT_RESULT/ORDER_OBSERVATION/ORC-4");
// ORC-4 will still exist (but be empty) even if ORC has no content
String encoded = parser.encode(message);
See the JavaDoc for examples.

How to get the underlying object from a SpyMessage in JBossMQ

I am trying to write a simple Java program that reads from JBossMQ's jms_messages table using JDBC. I am using JBoss 4.0.4.GA.
I can get the as far as getting a SpyMessage, but how can I get the actual message content (which is an Object in the particular case I'm looking at).
I have a result set "rs" from this statement:
SELECT messageid, messageblob FROM jms_messages WHERE DESTINATION LIKE 'TOPIC.MyTopic%' limit 3"
and then I do this (based on JBoss code):
long messageid = rs.getLong(1);
SpyMessage message = null;
byte[] st = rs.getBytes(2);
ByteArrayInputStream baip = new ByteArrayInputStream(st);
ObjectInputStream ois = new ObjectInputStream(baip);
message = SpyMessage.readMessage(ois);
message.header.messageId = messageid;
String jmstype = message.getJMSType();
String jms_message_id = message.getJMSMessageID();
System.out.println("jmstype=" +jmstype);
System.out.println("jms_message_id=" +jms_message_id);
String propertyName;
Enumeration e = message.getPropertyNames();
while (e.hasMoreElements())
{
propertyName = (String)e.nextElement();
System.out.println("property name = " +propertyName);
}
but I get no properties printed and I don't know how to get my actual object from the SpyMessage (actually a SpyObjectMessage). I'd be grateful for any pointers.
I've tried asking this question on the JBoss forum without reply, so I'm hoping for better luck here.
Thanks.
Sorry - the answer was so obvious I'm not really sure what I was thinking when I posted the question - simply:
Object objMessage = ((SpyObjectMessage)message).getObject();

Why is GWT ArrayList of String objects truncating text with an ampersand?

I'm using GWT on the client side. I store String objects in an ArrayList instance, and when I add the value "AT&T", it only seems to be storing "AT". I suspect this is the result of the ArrayList truncating the text due to the ampersand, but I have yet to write a smaller proof-of-concept to be sure. Has anyone else encountered this problem?
GWT 2.1.1
Tomcat 7.0.5
Firefox 5.0.1
So this test succeeds:
ArrayList<String> test = new ArrayList<String>();
test.add( "testing&123");
Window.alert( test.get(0) + " - " + test.get(0).contains("&") );
My code effectively does this:
String test = "AT&T";
MyApp.getInstance().getDataStore().add( test );
Window.alert( test + " - " + MyApp.getInstance().getDataStore().getItems().get(0) );
public void DataStore.add( String item ) {
itemsList.add( item );
}
public ArrayList<String> getItems() {
return itemList;
}
The output is "AT&T - AT". So if the ArrayList is not the problem, is it the method calls?
Well, it turns out it was an interaction between my History Manager and the DataStore class. A very strange situation that no one could have helped me with given the limited amount of information I had provided.