Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
epswing
Nov 4, 2003

Soiled Meat
The scenario: MyApp (console application) would like to run another program (SomeProgram, but this can really be any program which works with stdin and cmd-line args) in a new console window. My current platform is Windows XP and java version "1.6.0_03".

MyApp uses Runtime.getRuntime().exec to launch the other program. Assuming the other program is a java program SomeProgram, I'd want to execute the command "cmd /C java SomeProgram arg1 arg2 arg3", send some stdin data, and this works great with my current code. To launch the other program in a new console window, I'd want to execute the command "cmd /C start java SomeProgram", note the 'start'. You can try this yourself by opening a console and typing "cmd /C start echo hi there" or "cmd /C start pause".

The trouble is, when using cmd's "start", the stdin I send never makes it to the launched program.

Save the following to MyApp.java
code:
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

public class MyApp {
	
	public static final String newline = System.getProperty("line.separator");
	
	public static void main(String[] args) throws Exception {
		
		// works:
		String[] command = { "cmd", "/C", "java", "SomeProgram", "arg1", "arg2", "arg3" };
		
		// doesn't work:
		//String[] command = { "cmd", "/C", "start", "java", "SomeProgram", "arg1", "arg2", "arg3" };
		
		File path = new File(".");
		
		StringBuffer stdin = new StringBuffer();
		stdin.append("hey here are some lines" + MyApp.newline);
		stdin.append("that should be coming in on stdin" + MyApp.newline);
		stdin.append("" + MyApp.newline);
		stdin.append("empty line above me" + MyApp.newline);
		stdin.append("ok we're done" + MyApp.newline);
		
		System.out.println("executing process");
		Process process = Runtime.getRuntime().exec(command, null, path);
		
		System.out.println("sending stdin");
		InputStream in = new ByteArrayInputStream(stdin.toString().getBytes());
		OutputStream out = process.getOutputStream();
		int len = 32;
		int count = 0;
		byte[] buffer = new byte[len];
		while ((count = in.read(buffer, 0, len)) != -1)
			out.write(buffer, 0, count);
		out.close();
		in.close();
		
		System.out.println("collecting stdout and stderr");
		StringBuffer stdout = new StringBuffer();
		StringBuffer stderr = new StringBuffer();
		StreamGobbler.newStreamGobbler(process.getInputStream(), stdout);
		StreamGobbler.newStreamGobbler(process.getErrorStream(), stderr);
		
		System.out.println("waiting for process to finish");
		process.waitFor();
		
		System.out.println("process finished");
		System.out.println("stdout: [" + stdout.toString() + "]");
		System.out.println("stderr: [" + stderr.toString() + "]");
	}
	
}

/**
 * A quick class to empty out the stdout/stderr streams of a running process,
 * appending them to a StringBuffer.
 */
class StreamGobbler extends Thread {
	
	public static StreamGobbler newStreamGobbler(InputStream input, StringBuffer output) {
		StreamGobbler s = new StreamGobbler(input, output);
		s.start();
		return s;
	}
	
	private InputStream input;
	private StringBuffer output;
	
	private StreamGobbler(InputStream input, StringBuffer output) {
		this.input = input;
		this.output = output;
	}
	
	public void run() {
		try {
			InputStreamReader isr = new InputStreamReader(input);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null)
				output.append(line + MyApp.newline);
			br.close();
			isr.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
}
Save the following to SomeProgram.java
code:
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class SomeProgram {
	
	public static void main(String[] args) throws Exception {
		
		System.out.println("Command-line arguments:");
		for (String arg : args)
			System.out.println("\t" + arg);
		
		System.out.println();
		
		System.out.println("Standard in:");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line = "";
		while ((line = br.readLine()) != null)
			System.out.println("\t" + line);
	}
}
Simply compile both java files and run "java MyApp" to see it in action. To see where I'm having trouble, comment/uncomment the two versions of String[] command near the top of MyApp.java.

SomeProgram could really be any program that deals with stdin. I happen to be launching TCL scripts, so my command looks more like "cmd /C start tclsh SomeScript.tcl arg1 arg2 arg3".

Any other comments would be appreciated, for example I'm not sure if I need to be sending stdin like I am, considering it'll always be string data.

Edit: What I'm suspecting is that "start" is cockblocking the program I wish to execute out of the stdin I want to pass it. There's no way to pass the stdin through start?

epswing fucked around with this message at 15:41 on Apr 2, 2008

Adbot
ADBOT LOVES YOU

epswing
Nov 4, 2003

Soiled Meat

zootm posted:

"start" ignores input. Your Java code is working fine, but start spawns and starts a new console window for you and that's all it does.

What is it you're trying to do? There's bound to be a better way to do this?

In short (really short), MyApp is a server which schedules and launches scripts. MyApp, among other places, logs to the console, so it would be nice to pop up a new console window to allow visual monitoring of currently-executing scripts without polluting the main console window.

One solution would be to launch a JFrame with the process and dump stdout/stderr to a textarea as it rolls out. I didn't want to use Swing in this piece of my puzzle, but it would probably work well, now that I think about it.

I'm betting I could make the JFrame look pretty close to a real console too...

epswing
Nov 4, 2003

Soiled Meat

zootm posted:

If you're just wanting to catch logging, however, use a standard logging toolkit like log4j or java.util.logging or Commons Logging or whatever and...

Yep, I'm using log4j extensively, this is just to present the user with some visual feedback that what MyApp is running is actually running.

epswing
Nov 4, 2003

Soiled Meat
What do you mean by "Just capture the logging information directly"? I'm spawning a process, how else do you propose I capture it's stdout/err?

epswing
Nov 4, 2003

Soiled Meat

fletcher posted:

Is there a way to do this without int count?

There are lots of ways...

code:
StringBuilder qry = new StringBuilder();
// ...
Iterator accountIds = accounts.keySet().iterator();
while (accountIds.hasNext())
	qry.append("'" + accountIds.next() + "',");
if (qry.charAt(qry.length()-1) == ',')
	qry.deleteCharAt(qry.length()-1)
Edit: Here's what we should be doing, regarding the conversation below:

code:
StringBuilder qry = new StringBuilder();
// ...
Iterator accountIds = accounts.keySet().iterator();
while (accountIds.hasNext()) {
	qry.append("'");
	qry.append(accountIds.next());
	qry.append("',");
}
if (qry.charAt(qry.length()-1) == ',')
	qry.deleteCharAt(qry.length()-1)

epswing fucked around with this message at 21:41 on Apr 8, 2008

epswing
Nov 4, 2003

Soiled Meat

Brain Candy posted:

Just check that length is non-zero instead?
Nope, depends on if qry already has content such as "select ...".

triplekungfu posted:

epswing & Brain Candy: I was under the impression that the compiler will take care of substituting StringBuilder during string concatenation?
Sounds like this will create a new StringBuilder instance per iteration, in which case the extra append calls would be better.

epswing
Nov 4, 2003

Soiled Meat

TRex EaterofCars posted:

Why would the compiler do that?

I don't know anything about the java compiler. From my lofty perch, far from such low-level details, it sounds like
code:
String s1 = "hello" + "there";
conceptually amounts to something like
code:
String s1;
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append("there");
s1 = sb.toString();
Are there StringBuilder instances lying around that the VM uses on a per-thread basis for all String + String concat operations? I'm interested to know how this works.

epswing fucked around with this message at 16:58 on Apr 8, 2008

epswing
Nov 4, 2003

Soiled Meat

TRex EaterofCars posted:

...and it uses .append() with only 1 instance of StringBuilder.

That's exactly what I was concerned with: does the following mean 5 instances of StringBuilder?

code:
public class StringDemo {
        public static void main(String [] args) {
                for (int i = 0; i < [b]5[/b]; i++) {
                        String s1 = "Hello";
                        String s2 =  " ";
                        String s3 = " world!";
                        String s4 = s1 + s2 + s3;
                        System.out.println(s4);
                }
        }
}

epswing
Nov 4, 2003

Soiled Meat

TRex EaterofCars posted:

Sure does.

Ok, which brings me back to http://forums.somethingawful.com/showthread.php?threadid=2780384&pagenumber=5#post342041228

epswing posted:

Sounds like this will create a new StringBuilder instance per iteration, in which case the extra append calls would be better.

TRex EaterofCars posted:

Why would the compiler do that?

Looks like it would. In which case I'm saying that N*3 calls to append might be faster than N new StringBuilder objects.

epswing
Nov 4, 2003

Soiled Meat
Here's how I set my column widths:

code:
table.getColumn("User").setMaxWidth(75);
table.getColumn("Start Time").setMinWidth(130);
table.getColumn("End Time").setMinWidth(130);

epswing
Nov 4, 2003

Soiled Meat

TRex EaterofCars posted:

I'll post the code if anyone wants

I'd love to see it firsthand. :)

epswing
Nov 4, 2003

Soiled Meat

Brain Candy posted:

In the code block you gave, you constructed qry inside the block. So if your while loop executes at least once, the last char of qry will be ','.

Look at what fletcher gave us initially, there's a qry variable out of nowhere, it could contain anything. I instantiated a StringBuilder in my block because I needed a StringBuilder instead of a String, I clearly needed to indicate this somehow, but that's not necessarily where he/she is instantiating it. (That's what the // ... is for.)

(Edit: Yay, first time I use [fixed]!)

epswing fucked around with this message at 06:21 on Apr 9, 2008

epswing
Nov 4, 2003

Soiled Meat

clayburn posted:

Simple question I think. I have a very long string, that I want to take all n-length substrings out of and place into an array. For example if n is 5 and the sentence is "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt whatever", I would want string one to be "Lorem ipsum dolor sit amet,"
, string two to be "ipsum dolor sit amet, consectetur", string three to be "dolor sit amet, consectetur adipisicing", and so on. What would be the best way to go about this? I am having a hard time getting anything to work really.

Smells like homework. You probably want to take a look at the String.split method, or the StringTokenizer class. Before writing code, however, you should think about the problem and devise a strategy to tackle it. Think about what loops you'll need where (assuming recursion isn't in the picture yet).

Wouldn't it be nice if all the words in your string were in an array that you could loop over? ;)

epswing fucked around with this message at 07:50 on Apr 17, 2008

epswing
Nov 4, 2003

Soiled Meat
Regarding hashCode and equals, it's really important that java developers read and understand this: http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

e: fixed link

epswing fucked around with this message at 15:46 on Apr 22, 2008

epswing
Nov 4, 2003

Soiled Meat
I've had decent results using Cavaj.

epswing
Nov 4, 2003

Soiled Meat

Thlom posted:

After some investigation it seems like the nullpointerexceptions gets thrown at
code:
Statement stmt = con.createStatement();

Looks like you may have a connection problem. The rest of the implementation looks like it would work. Check if con == null, and if it is, then you were never connected in the first place, so that's what you should focus on at this point.

epswing
Nov 4, 2003

Soiled Meat
Well the docs say "SQLException - if a database access error occurs". They don't say whether "access error" means there was an error with your login information (permission problem), or if there was an error communicating with the database.

In any case, a NPE occurring at a line with obj.methodCall() means obj was null.

epswing
Nov 4, 2003

Soiled Meat
dancavallaro that sounds like a fun project, are you using a library to interpret the request and send the response?

epswing
Nov 4, 2003

Soiled Meat
Well the first thing that comes to mind in the Java realm is Tomcat. I'm sure somewhere in servlet.jar there are classes to deal with HTTP requests/responses.

e: http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html

epswing fucked around with this message at 18:58 on May 16, 2008

epswing
Nov 4, 2003

Soiled Meat

lekki posted:

That's not such a good idea. Check your cpu usage , it should be 100%. Let the thread sleep for some time or use wait().

Untrue, ServerSocket's accept() blocks like wait(). http://java.sun.com/javase/6/docs/api/java/net/ServerSocket.html#accept()

quote:

Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.

epswing fucked around with this message at 21:30 on May 18, 2008

epswing
Nov 4, 2003

Soiled Meat
Try and code yourself a working example independent of your real project. It should contain only the code necessary for what you want to do. If that example doesn't work, it's easy to pass around to others and ask "why doesn't line XX do what I think it's supposed to do?"

epswing
Nov 4, 2003

Soiled Meat

zootm posted:

I'm interested to know what language the stuff within the <%= %>-delimited block is

In JSP, <% out.println("this"); %> is the same as <%= "this" %>, like PHP short-tags.

e: Whoops, I didn't see those ampersands. What the hell is that, then?

epswing fucked around with this message at 19:12 on May 21, 2008

epswing
Nov 4, 2003

Soiled Meat
As long as you don't think that a Java app will magically be cross platform. You'll have to be diligent when working with line endings, file io, stdin/stdout, OS paths, etc. The facilities are there for you to work with, you just have to remember to use them.

epswing
Nov 4, 2003

Soiled Meat

shodanjr_gr posted:

Found what i needed

code:
Runtime run = Runtime.getRuntime();
Process p = run.exec("cmd.exe /C "+this.my_file.getCanonicalPath());

You'll probably want to use ProcessBuilder.

epswing
Nov 4, 2003

Soiled Meat

shodanjr_gr posted:

..but i am wondering if there is a more "generic" way to do it.

There is, you probably want a shutdown hook. Here's how I usually do it:

code:
public class YourMainClass {
	public YourMainClass() {
		Runtime.getRuntime().addShutdownHook(new ShutdownHook(this));
	}
}

class ShutdownHook extends Thread {
	YourMainClass prog;
	public ShutdownHook(YourMainClass prog) {
		this.prog = prog;
	}
	public void run() {
		System.out.println("Shutting down...");
		prog.closeThingy();
		prog.disconnectStuff();
		prog.turnOffLights();
		System.out.println("Bye!");
	}
}

epswing
Nov 4, 2003

Soiled Meat
God I hate Java GUI work. HATE.

So I've got this JFrame, let's call him 'happy'. Happy's just sitting there, chillin', he's got buttons and tabs and whatnot. In the same JVM, I start up a class which creates a ProcessBuilder and runs a process. Happy has nothing to do with any of this, can't see the ProcessBuilder, or the class that created it. This process started by ProcessBuilder has precious stdout and stderr InputStreams, which I gleefully want to display to the user in a brand spankin' new JFrame, let's call him 'motherfucker'. So the ProcessBuilder starts the process it's assigned to start and I spin up two threads to loop over the stdout and stderr I'm getting from that process. These two threads have the same instance of montherfucker, and in their loops are calling an append method to append their lines to a textarea sitting in motherfucker.

Here's the code those two threads are using to gobble up all the stdout and stderr of the running process:
code:
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
	motherfucker.append(line);
}
br.close();
isr.close();
Remember, there are two threads running the above code, for one of them input is the stdout I'm getting out of some running process, and for the other input is the stderr. Each of them also have the same instance of motherfucker, which I'm appending lines to by calling a method.

But wait! How am I appending lines to the textarea sitting in motherfucker? You bet your rear end I'm using SwingUtilities.invokeLater. Here's the append method sitting in motherfucker:

code:
public void append(final String line) {
	SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			textarea.append(line + "\n");
		}
	});
}
So this is all fine and dandy. Motherfucker works like a charm. The problem is that happy is completely unresponsive until the process started by ProcessBuilder quits.

WHY?

epswing
Nov 4, 2003

Soiled Meat
Well here's one for you: one of the processes I spawn and collect stdout/stderr from, well I just wrote a quick tcl script which prints hello, waits 45 seconds, prints goodbye, and exits. It looks like this:

code:
puts 'hi'
after 45000
puts 'bye'
exit 0
So that's what is coming in on stdout. So the stream that gobbles up stdout grabs the 'hi', and should sit there, blocked, for 45 seconds. And it does. And during this time, Mr. Happy is still frozen.

Here's another one for you: If I comment out the contents of the append method in the motherfucker jframe (so, zero calls to invokeLater), I get the same behavior.

code:
public void append(final String line) {
	/*SwingUtilities.invokeLater(new Runnable() {
		public void run() {
			textarea.append(line + "\n");
		}
	});*/
}
Edit: Forgot this guy: :psyduck:

epswing fucked around with this message at 08:21 on Jun 4, 2008

epswing
Nov 4, 2003

Soiled Meat
Right before looping over the InputStreams I put a System.err.println("reading input " + input + " on thread " + Thread.currentThread().getName());. The output was:

code:
reading input java.io.BufferedInputStream@1301ed8 on thread Thread-2
reading input java.io.FileInputStream@a37368 on thread Thread-3
Here's another one for you, the two jframes are basically two separate programs, each running in their own javaw.exe with their own main method, etc.

How is this possible.

epswing
Nov 4, 2003

Soiled Meat

1337JiveTurkey posted:

I think that SwingUtilities.isEventDispatchThread() is exactly what you guys are looking for.

The thread creating the ProcessBuilder and both threads sucking up with stdout/err are isEventDispatchThread() == false. (<-- edit: typo)

Twitchy: I guess I'll be putting together a working example, which is going to be a bitch, but at this point what choice do I have. I've removed the motherfucker jframe from the scenario completely and happy still freezes, inexplicably. I must have something else going wrong. :psyduck:

I loving hate GUI/Swing work. This is the kind of stuff that makes me want to quit my job and go into pig farming. It's challenging, but for all the wrong reasons. :smith:

epswing fucked around with this message at 18:38 on Jun 4, 2008

epswing
Nov 4, 2003

Soiled Meat

epswing posted:

The thread creating the ProcessBuilder and both threads sucking up with stdout/err are isEventDispatchThread() == true.

zootm posted:

Then the sucking threads are not being run in separate threads, they're running in the same thread as UI, for whatever reason. That result seems to mean that everything is running in the same thread.

OH sorry, that should be isEventDispatchThread() == false. They're all false, all NOT on the event dispatch thread.

epswing
Nov 4, 2003

Soiled Meat

Phillyt posted:

Where can I find the source code for an API library or whatever? I'm trying to find one of the packages in javax.swing but I haven't had much look with Google or looking in my own folders.

Look in your jdk directory (mine is C:\Program Files\Java\jdk1.6.0_02), I have a src.zip file with the entire java core.

epswing
Nov 4, 2003

Soiled Meat
I'm curious, what are you using a new double[1000][10000] for?

epswing
Nov 4, 2003

Soiled Meat
mistermojo: Also, it's imperative to understand how return values work.

For example,

code:
array = search(args);
sortedarray = bubblesort(array);
lineprinter(sortedarray);
is the same as

code:
lineprinter(bubblesort(search(args)));
without having to use explicit variables.

epswing
Nov 4, 2003

Soiled Meat

fletcher posted:

What's a good way to store a table of information? I want to use the same function and be able to output the results as an HTML table or as an excel spreadsheet using the POI HSSF stuff. There's a mix between strings, ints, etc that are going to go in the table.

You might want to consider something out of the Swing library, namely the model that JTables use, TableModel. You can write your own implementation, or extend the existing DefaultTableModel to suit your needs.

epswing
Nov 4, 2003

Soiled Meat
In an RDBMS, it's typical to normalize something like UserType (or PaymentMethod) into into its own table like 1=admin, 2=viewer (or 1=cash, 2=cheque, 3=creditcard), and other tables reference them by id. Such tables won't change, typically. In Java code, it makes sense to think of these as enums, so a Payment class would have a PaymentMethod field, where PaymentMethod is an enum: PaymentMethod.CASH, PaymentMethod.CHEQUE, etc.

How can I use Hibernate to represent this common use case?

The following links are what google has to say about the issue, but these solutions seem overly complex and/or are several years old.

http://www.hibernate.org/265.html
http://www.hibernate.org/265.html
http://appfuse.org/display/APF/Java+5+Enums+Persistence+with+Hibernate
http://www.hibernate.org/272.html
http://snipplr.com/view/5379/java-5-enum-hibernate-mapping/
http://hibernate.org/203.html

Does anyone have experience with this, and/or can vouch for one of the linked solutions?

Enlighten me!

(E: Don't get me wrong, I'm usually all for just trying things out, but the linked solutions look old, long and complicated, and this very well may be a case of someone here saying "oh just do X, it works great".)

epswing fucked around with this message at 17:52 on Dec 5, 2008

epswing
Nov 4, 2003

Soiled Meat

Coca Koala posted:

For my final project in my intro java class, I need to code minesweeper with an animated timer.

You could extend the JPanel class, something like
code:
public class MineSweeperCell extends JPanel {
  private boolean bomb;
  public MineSweeperCell(boolean bomb) {
    this.bomb = bomb;
  }
  public isBomb() { return bomb; }
}
So now you just need one 2d array of JPanels, and each has an extra isBomb() method you can call to see if they're a bomb or not.

(I know someone is going to say "gadzooks, you're embedding application logic in a gui component, that's filthy", but c'mon, it's an intro course.)

Edit: vvv Sure, whichever component he ends up using! The point I was trying to emphasize was not needing two 2d arrays.

epswing fucked around with this message at 17:00 on Dec 7, 2008

epswing
Nov 4, 2003

Soiled Meat
I'm finding your reply somewhat vague. What do you mean by "that way"? Can you give an example?

epswing
Nov 4, 2003

Soiled Meat

Brain Candy posted:

Yes, yes, but if you use arrays enough to require a helper method you've got more problems than making the arrays.

This is easy to say without actually sitting in front of code/libs which you may or may not have the power to change.

epswing
Nov 4, 2003

Soiled Meat

Kilson posted:

It doesn't stop or exit, it just continues running (after skipping whatever code it skips) as if nothing ever happened.

I've had this happen to me before in tomcat/spring. I couldn't believe it. Everything in a controller was in a try/catch(Throwable) { log('hi!') }, something was breaking, yet the page would still partially load in the browser, no errors.

Never could explain why/how.

Adbot
ADBOT LOVES YOU

epswing
Nov 4, 2003

Soiled Meat

fletcher posted:

I've got a string with an HTML snippet in it. I need a List of innerHTML for all the table cell elements. A regexp seems like the right tool, I'm just horrible at it. Can anybody help me out?
code:
import java.io.ByteArrayInputStream;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

public class InnerHtml {
	
	public static void main(String[] args) throws Exception {
		
		String html =
			"<table>" +
				"<tr>" +
					"<td>one</td><td>two</td><td>three</td>" +
				"</tr>" + 
				"<tr>" +
					"<td>four</td><td>five</td><td>six</td>" +
				"</tr>" +
			"</table>";
		
		String xpath = "//td";
		
		Document document = new SAXBuilder().build(new ByteArrayInputStream(html.getBytes()));
		List<Element> elements = XPath.newInstance(xpath).selectNodes(document);
		
		for (Element element : elements) {
			System.out.println(element.getTextTrim());
		}
	}
}
...prints...
code:
one
two
three
four
five
six
Ensure you have jdom and jaxen on the classpath.

epswing fucked around with this message at 08:31 on Nov 6, 2009

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply