Start JavaFX application on new JVM via code [duplicate] - exception

Can a Java application be loaded in a separate process using its name, as opposed to its location, in a platform independent manner?
I know you can execute a program via ...
Process process = Runtime.getRuntime().exec( COMMAND );
... the main issue of this method is that such calls are then platform specific.
Ideally, I'd wrap a method into something as simple as...
EXECUTE.application( CLASS_TO_BE_EXECUTED );
... and pass in the fully qualified name of an application class as CLASS_TO_BE_EXECUTED.

This is a synthesis of some of the other answers that have been provided. The Java system properties provide enough information to come up with the path to the java command and the classpath in what, I think, is a platform independent way.
public final class JavaProcess {
private JavaProcess() {}
public static int exec(Class klass, List<String> args) throws IOException,
InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getName();
List<String> command = new LinkedList<String>();
command.add(javaBin);
command.add("-cp");
command.add(classpath);
command.add(className);
if (args != null) {
command.addAll(args);
}
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.inheritIO().start();
process.waitFor();
return process.exitValue();
}
}
You would run this method like so:
int status = JavaProcess.exec(MyClass.class, args);
I thought it made sense to pass in the actual class rather than the String representation of the name since the class has to be in the classpath anyways for this to work.

Two hints:
System.getProperty("java.home") + "/bin/java" gives you a path to the java executable.
((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURL() helps you to reconstruct the classpath of current application.
Then your EXECUTE.application is just (pseudocode):
Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)

This might be an overkill for you, but Project Akuma does what you want and more.
I found it via this entry at Kohsuke's (one of Sun's rock start programmers) fabulously useful blog.

Expanding on #stepancheg's answer the actual code would look like so (in the form of a test).
import org.junit.Test;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.stream.Collectors;
public class SpinningUpAJvmTest {
#Test
public void shouldRunAJvm() throws Exception {
String classpath = Arrays.stream(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs())
.map(URL::getFile)
.collect(Collectors.joining(File.pathSeparator));
Process process = new ProcessBuilder(
System.getProperty("java.home") + "/bin/java",
"-classpath",
classpath,
MyMainClass.class.getName()
// main class arguments go here
)
.inheritIO()
.start();
int exitCode = process.waitFor();
System.out.println("process stopped with exitCode " + exitCode);
}
}

Did you check out the ProcessBuilder API? It's available since 1.5
http://java.sun.com/javase/6/docs/api/java/lang/ProcessBuilder.html

public abstract class EXECUTE {
private EXECUTE() { /* Procedural Abstract */ }
public static Process application( final String CLASS_TO_BE_EXECUTED ) {
final String EXEC_ARGUMENT
= new StringBuilder().
append( java.lang.System.getProperty( "java.home" ) ).
append( java.io.File.separator ).
append( "bin" ).
append( java.io.File.separator ).
append( "java" ).
append( " " ).
append( new java.io.File( "." ).getAbsolutePath() ).
append( java.io.File.separator ).
append( CLASS_TO_BE_EXECUTED ).
toString();
try {
return Runtime.getRuntime().exec( EXEC_ARGUMENT );
} catch ( final Exception EXCEPTION ) {
System.err.println( EXCEPTION.getStackTrace() );
}
return null;
}
}

Do you really have to launch them natively? Could you just call their "main" methods directly? The only special thing about main is that the VM launcher calls it, nothing stops you from calling main yourself.

Following on what TofuBeer had to say: Are you sure you really need to fork off another JVM? The JVM has really good support for concurrency these days, so you can get a lot of functionality for relatively cheap by just spinning off a new Thread or two (that may or may not require calling into Foo#main(String[])). Check out java.util.concurrent for more info.
If you decide to fork, you set yourself up for a bit of complexity related to finding required resources. That is, if your app is changing frequently and depends upon a bunch of jar files, you'll need to keep track of them all so that they can be passed out to the classpath arg. Additionally, such an approach requires to to infer both the location of the (currently executing) JVM (which may not be accurate) and the location of the current classpath (which is even less likely to be accurate, depending upon the way that the spawning Thread has been invoked - jar, jnlp, exploded .classes dir, some container, etc.).
On the other hand, linking into static #main methods has its pitfalls as well. static modifiers have a nasty tendency of leaking into other code and are generally frowned upon by design-minded folks.

A problem that occurs when you run this from a java GUI is it runs in the background.
So you cannot see the command prompt at all.
To get around this, you have to run the java.exe through "cmd.exe" AND "start".
I dont know why, but if you put "cmd /c start" infront it shows the command prompt as it runs.
However, the problem with "start" is that if there is a space in the path to the application
(which the path to the java exe usually have as it is in
C:\Program Files\Java\jre6\bin\java.exe or similar),
then start just fails with "cannot find c:\Program"
So you have to put quotes around C:\Program Files\Java\jre6\bin\java.exe
Now start complains about parameters that you pass to java.exe:
"The system cannot find the file -cp."
Escaping the space in "Program Files" with a backslash also does not work.
So the idea is to not use space.
Generate a temporary file with the bat extension and then put your command with spaces in there
and run the bat.
However, running a bat through start, does not exit when done,
so you have to put "exit" at the end of the batch file.
This still seems yucky.
So, looking for alternatives, I have found that using quote space quote in the space of "Program Files" actually works with start.
In the EXECUTE class above change the string builder appends to:
append( "cmd /C start \"Some title\" " ).
append( java.lang.System.getProperty( "java.home" ).replaceAll(" ", "\" \"") ).
append( java.io.File.separator ).
append( "bin" ).
append( java.io.File.separator ).
append( "java" ).
append( " " ).
append( new java.io.File( "." ).getAbsolutePath() ).
append( java.io.File.separator ).
append( CLASS_TO_BE_EXECUTED ).

Related

how can i determine the working directory a fatjar was invoked from

I have a project which i have made into a fatjar. Gradle pus this into the /build/libs
I have gone to this directory and invoked the fatjar with a file as a param.
steps
cd /build/libs
java -jar .jar --execute script.groovy
this launches the Main-Class - a launcher class that reads the args from command line.
however what you get as the file name is 'script.groovy' and thats intended to be from the same directory as i have the jar file
Inside the class /fatjar however if you look at
System.getProperty("user.dir")
or
Path path = FileSystems.getDefault().getPath(".").toAbsolutePath()
they all report the path as the projectRoot directory - and not where the jar itself was run from (/build/libs)
inside your class, inside the fatjar, how do you determine the directory where the fatjar actually is when invoked from the command line?
I struggled a bit on this as well. You can find some hints in StartupInfoLogger.java from spring. I am using 2.1.5 spring boot version.
Here is some sample code.
public class MyTestFatJarMainClass {
public static void main(String[] args) {
SpringApplication.run(MyTestFatJarMainClass.class, args);
// The needed code start below
// The class is MyTestFatJarMainClass.class, but it can be any class in your app
ApplicationHome home = new ApplicationHome(MyTestFatJarMainClass.class);
String path = (home.getSource() != null) ? home.getSource().getAbsolutePath() : "";
// Now you got the path, it contains the jar file itself.
System.out.println("DINDA " + s + " path " + path);
}
}
You could also read String property = System.getProperty("user.dir");
Check which one of them can be useful for you.

Find string length without using builtin string.length method in web methods?

I want to find length of given string with out using pub.string.length (built in function) in web methods .
Ex:If we give name "abcdef" i want result like 6 .
You could write your own java service, but that sounds redundant to me.
Here's an (as yet untested) code sample:
public static final void checkStringSize(IData pipeline)
throws ServiceException {
// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
String inputString = IDataUtil.getString( pipelineCursor, "inputString" );
pipelineCursor.destroy();
long length = -1;
length = inputString.length();
// pipeline
IDataCursor pipelineCursor_1 = pipeline.getCursor();
IDataUtil.put( pipelineCursor_1, "length", ""+length );
pipelineCursor_1.destroy();
}
You could manually count the length of the string by using pub.string:substring until it gets an error.
I wouldn't recommend this - it's inelegant, possibly quite slow and it still uses a function from pub.string, which you appear to be avoiding.
Anyway, here's a way to do it, click the link to see the image.
webMethods code sample - https://i.stack.imgur.com/FE9oU.jpg
Just make sure the input string cannot be null - otherwise the substring won't throw an error and it will have an infinite loop.

PHP namespace behaviour gives FATAL error with spl_autoload_register

I want to use namespace and spl_autoload_register together but failed with different error each time.
Please See complete code files on github.
Below are the files
a base file where create a class with namespace class.alpha.php
an include file where I define spl_autoload_register include.php
an example file which instantiate the class object eg.php
Now when I create object from eg.php it gives FATAL error but when I comment namespace line in class.alpha.php then it's working
Please see the code below.
alpha.class.php
<?php
//namespace Alpha; //<< comment and uncomment this to regenerate the error
class Alpha
{
// public static $baseDir_;
public $dir = __DIR__;
public static $baseDir_;
public function __construct()
{
echo __FILE__."=>".__METHOD__;
var_dump(self::$baseDir_, $this->dir);
$firstDir = !empty(self::$baseDir_) ? self::$baseDir_ : $this->dir;
}
}
include.php
<?php //namespace Alpha\config;
spl_autoload_extensions(".php");
spl_autoload_register('loadclass');
function loadclass($class)
{
try {
if (is_readable(strtolower($class).".class.php")) {
include_once strtolower($class).".class.php";
}
} catch (Exception $e) {
print "Exception:". $e;
}
}
//#link http://php.net/manual/en/function.spl-autoload-register.php
// spl_autoload_register(__NAMESPACE__.'Alpha\Alpha()' );
eg.php
<?php
require_once 'include.php';
/** below code works by commenting 1st line on alpha.class.php
if we un comment then below code gives Fatal error: Class 'Alpha' not found */
Alpha::$baseDir_ = '/opt/lampp/archive/';
$obj_ = new Alpha();
var_dump(get_included_files());
var_dump($obj_);
/** now we define namespace Alpha on alpha.class.php */
// $ns_ = new Alpha\Alpha(); // Fatal error: Class 'Alpha\Alpha' not found
// var_dump($ns_);
/** not working even with use statement */
// use Alpha;
// use Alpha;
// $fn = new Alpha\Alpha();
// var_dump($fn);
Please help me out to solve this issue.
Thanks
Your autoloader is receiving a request for a class of "Alpha\Alpha" if you uncomment the namespace in alpha.class.php and place the use Alpha\Alpha in eg. This means that the location it's expecting to find your class in would be alpha\alpha.class.php.
Unless you're on Windows, directory separators are typically forward slash (/). So there's a number of possible solutions.
**Possible Solution #1 - Leave all files in the same place **
If you want to leave everything where it is now, you'll need to remove the namespace from the class names in the autoloader. If you add these lines to the top of your autoloader, that will make it behave that way:
$classParts = explode("\\", $class);
$class = $classParts[count($classParts) - 1];
I would not recommend this solution though since it means that you can no longer provide the same class name in a different namespace.
Possible Solution #2 - Put namespaces in subdirectories
For this solution, you'd create a new directory "alpha" and move "alpha.class.php" into it. For autoloader changes, you can add the following lines to the top of your autoloader:
$class = str_replace("\\", "/", $class);
This will change the namespace separators from backslashes to file path separators with forward slash. This will work on windows as well as mac and linux.
Possible Solution #3 - Follow an established autoloading standard
There are already a number of standard PHP autoloading standards. PSR-0 (now deprecated) works, but PSR-4 would be recommended:
PSR-0: http://www.php-fig.org/psr/psr-0/
PSR-4: http://www.php-fig.org/psr/psr-4/
One big upside of following one of these standards is that there are already plenty of implementations for them and there's been a lot of thought put into how they should work and maintain compatibility with other libraries you may end up wanting to use. Composer (http://getcomposer.org) will allow you to set up and use both PSR-0 and PSR-4 style autoloaders based on a very simple configuration.
Anyway, for the TL;DR crowd, the issue is that the autoloader receives the entire namespaced path in order to know how to load the class. The fatal error was because the autoloader wasn't properly mapping from that namespaced class to a file system location, so the file containing the class was never being loaded.
Hope this helps.

How to split messages file into multiple files in play 2.0 framework

I have a huge message file which i need to split into multiples files for different languages.
For example :
I created one folder for English locale i.e. en and another for French locale , fr inside conf folder.
en contains messages1_en.properties and messages2_en.properties
fr contains messages1_fr.properties and messages2_fr.properties
How to access these properties files inside my view.
Thanks
The only way to do that without introducing your own alternative implementation and use that instead of the built in Messages is to use hacked locales, so you would do fr_type1, fr_type2 or something like that to select the right alternative.
This is probably a bad idea since it's always risky to use an API in a different way from how it was intended to be used, there is a high risk of unexpected behaviour and it might be brittle since there is no guarantee that you will be able to use made up locales in future versions etc.
If you look at the Messages implementation you could probably get some ideas of how to implement your own without much fuss.
Good luck!
That's an old question, but i had a close issue, and i didn't find a solution anywhere.
This example use a configuration key to load messages from a file with a custom name. But you can easily modify it to load messages file from a subdirectory and/or multiple messages files.
Override play.api.i18n.DefaultMessagesApiProvider
#Singleton
class CustomMessagesApiProvider #Inject() (
environment: Environment,
config: Configuration,
langs: Langs,
httpConfiguration: HttpConfiguration)
extends DefaultMessagesApiProvider(environment, config, langs, httpConfiguration) {
def filename =
config.get[String]("play.i18n.filename")
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang, loadMessages(filename +"." + lang))
}.toMap
.+("default" -> loadMessages(filename))
.+("default.play" -> loadMessages(filename+".default"))
}
}
Add Guice binding in Module.java
#Override
public void configure() {
bind(DefaultMessagesApiProvider.class).to(CustomMessagesApiProvider.class);
}
It's my first Scala class, so maybe it can be improved. But it works.
To load multiple files (it compiles but not tested)
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang,
loadMessageFiles("." + lang))
}.toMap
.+("default" -> loadMessageFiles(""))
.+("default.play" -> loadMessageFiles(".default"))
}
private def loadMessageFiles(suffix: String) = {
loadMessages("messages-1" + suffix) ++ loadMessages("messages-2" + suffix)
}

Bundle Helper for bundling and splitting coffeescript

I was experimenting with Bundle and Minification in MVC4 and came across an interesting problem.
I am using Coffeescript and I would like a Render helper that works a bit like the #Scripts.Render() method.
For example, let's say I have this bundle config:
new ScriptBundle("~/bundle/appfiles").Include(
"~/Scripts/app/sample.js",
"~/Scripts/app/myApp.js");
In the cshtml, when I do #Scripts.Render() I get different results based on the debug setting in the web.config. If debug is true I get one script tag per file, otherwise I get a single script tag that returns the bundled and minified js. This is fine.
Let-s assume now that I want to do the same with my Coffeescripts. I create a bundle like this:
new Bundle("~/bundle/appfiles", new CoffeeBundler(), new JsMinify()).Include(
"~/Scripts/app/sample.coffee",
"~/Scripts/app/myApp.coffee");
The problem now is that if I use #Scripts.Render() I get, while in debug, one script per file but this is not transformed at all. The only use I could do is this:
<script type="text/javascript" src="#(BundleTable.Bundles.ResolveBundleUrl("~/bundle/appfiles"))"></script>
But this will, even in debug mode, bundle everything together and then minify, which of course is not what I want.
I have tried to create a Coffee.Render() helper similar to the Scripts one but it uses the AssetManager class which is internal to the System.Web.Optimization assembly.
I was wondering if you have an idea on how to do this in a clean way (i.e: using the available public classes, not copying and pasting the whole AssetManager code, not doing fancy Directory.EnumerateFiles when creating the bundle).
Thanks!
PS: I know that a quicker solution would be to use Mindscape Workbench and bundle the generated js files, I am looking for something that uses what the framework has, maybe also avoiding to have to tell the team to install a tool that people may not like...
In the end I went for a HtmlHelper solution for this. Still in early stage but working as I would like. It is detailed in a blog post for the time being.
Here is the full Helper code in case the blog goes lost...
public static class HtmlHelperExtensions
{
public static MvcHtmlString RenderCoffeeBundle(this HtmlHelper htmlHelper, string virtualPath)
{
if (String.IsNullOrEmpty(virtualPath))
throw new ArgumentException("virtualPath must be defined", "virtualPath");
var list = GetPathsList(virtualPath);
//TODO: Nice and cleaner EliminateDuplicatesAndResolveUrls(list);
var stringBuilder = new StringBuilder();
foreach (string path in list)
{
stringBuilder.Append(RenderScriptTag(path));
stringBuilder.Append(Environment.NewLine);
}
return MvcHtmlString.Create(stringBuilder.ToString());
}
private static IEnumerable<string> GetPathsList(string virtualPath)
{
var list = new List<string>();
if (BundleResolver.Current.IsBundleVirtualPath(virtualPath))
{
if (!BundleTable.EnableOptimizations)
{
foreach (var path in BundleResolver.Current.GetBundleContents(virtualPath))
{
var bundlePath = "~/autoBundle" + ResolveVirtualPath(path.Replace("coffee", "js"));
BundleTable.Bundles.Add(new Bundle(bundlePath, new CoffeeBundler()).Include(path));
// TODO: Get the actual CustomTransform used in the Bundle
// rather than forcing "new CoffeeBundler()" like here
list.Add(bundlePath);
}
}
else
list.Add(BundleResolver.Current.GetBundleUrl(virtualPath));
}
else
list.Add(virtualPath);
return list.Select(ResolveVirtualPath).ToList();
}
private static string RenderScriptTag(string path)
{
return "<script src=\"" + HttpUtility.UrlPathEncode(path) + "\"></script>";
}
private static string ResolveVirtualPath(string virtualPath)
{
return VirtualPathUtility.ToAbsolute(virtualPath);;
}
}
I'm sorry I'm not addressing your exact question, but I do want to speak to your PS at the end of the post.
At this time, I don't really think we have a "no tools" story, but I do agree with the sentiment of "using what the framework has".
To that end, I would strongly recommend using TypeScript. You don't have to learn a new language (like you do with CoffeeScript) and yet it gives you a strongly-typed version of JavaScript that you can use a lot more like c# (with type validation etc.).
It will take you 20 mins to go through some of the tutorials:
http://www.typescriptlang.org/Playground/
Or, better yet, have a look at the BUILD session from the fall:
http://channel9.msdn.com/Events/Build/2012/3-012
Btw...if this isn't a direction you are wanting to go, no worries...I just find a lot of devs don't even know about TypeScript yet as an option.
Hope this helps in your quest to simplify things for your team.
Cheers.