Embedding swank-clojure in java program - java

Based on the Embedding section of http://github.com/technomancy/swank-clojure,
I'm using the following to test it out. Is there a better way to do
this that doesn't use Compiler? Is there a way to programmatically
stop swank? It seems start-repl takes control of the thread. What
would be a good way to spawn off another thread for it and be able to
kill that thread programatically.
import clojure.lang.Compiler;
import java.io.StringReader;
public class Embed {
public static void main(String[] args) throws Exception {
final String startSwankScript =
"(ns my-app\n" +
" (:use [swank.swank :as swank]))\n" +
"(swank/start-repl) ";
Compiler.load(new StringReader(startSwankScript));
}
}
Any help much appreciated,
hhh

Would it be acceptable to you to implement the Embed class in Clojure? You could do that with gen-class (see Meikel Brandmeyer's tutorial for details) and AOT compilation.
The code could go something like
(ns your-app.Embed
(:require [swank.swank :as swank])
(:gen-class
:methods [[startSwank [] void]]))
(defn -startSwank []
(swank/start-repl))
(add anything else you require); then in the Java part of your application, you could import your Clojure-prepared class, instantiate it and call .startSwank() on the instance.
Not sure about programmatically stopping Swank... I'd be curious to know of a good way to do that myself. (And I'll be back with an update if I figure it out; otherwise, I'd love to read somebody else's answer detailing how to go about that.)

Related

Issues using a Java interface in Clojure

I've been following this tutorial on distributed RMI using clojure, but it seems to be outdated and I can't get it to work:
http://nakkaya.com/2009/12/05/distributed-clojure-using-rmi/
I was getting a java.lang.ClassNotFoundException: stub.sayName when I followed the tutorial precisely, so I tried using reify instead of proxy, but the error is still there.
As of now my code is as follows:
for the interface:
package stub;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface sayName extends Remote {
String Name() throws RemoteException;
}
For my main clojure class:
(ns immutability.core
(:gen-class))
(defn -main
[& args]
(println "Hello, World!"))
(def rmi-registry
(java.rmi.registry.LocateRegistry/createRegistry 1099))
(defn name-server []
(reify stub.sayName Name
(Name [personname] "Hello, " + personname)))
(defn register-server []
(.bind
(java.rmi.registry.LocateRegistry/getRegistry)
"Hello"
(java.rmi.server.UnicastRemote/exportObject
(name-server) 0)))
(register-server)
I'm sure it's something silly and small, but I just can figure it out
Okay, these are your issues:
You need to add a package name to the java interface for it to work properly. On reading your post again, I can see the package name, it didn't get added to the code block... see below for where to put the SayName.class file.
You need to change the java signature to take a name, in accordance with your code
You need to change the reify signature, the one that you had previously just won't work. First the structure is wrong, and second, the method constructions are different in reify than proxy. With the reify forms, the arguments all need a reference to an anaphoric 'this', which I have replaced with _, since it is not in use in your code. The input argument is second in the form, and that is what you can use to set the name in "Hallo, Welt".
The class is java.rmi.server.UnicastRemoteObject, not java.rmi.server.UnicastRemote, as you have it in your original code.
Not really an error, but good to have, is to define the server symbol in clojure as defonce, so you don't end up with port conflicts when you try to re-evaluate the file, since the server is already defined.
Post these changes, the code compiles, and appears to be doing what it should. I stopped at invoking the RPI call.
interface code:
package stub;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface SayName extends Remote {
String name(String n) throws RemoteException;
}
I compiled and stored the stub.SayName interface in target/classes/stub/SayName.class. This is on the classpath and was found on the repl startup (relative to your project.clj file).
clojure code:
(ns immutability.core
(:gen-class))
(defn -main
[& args]
(println "Hello, World!"))
(defonce rmi-registry (java.rmi.registry.LocateRegistry/createRegistry 1099))
(defn name-server []
(reify stub.SayName
(name [_ n] (str "Hello " n))))
(defn register-server []
(.bind
(java.rmi.registry.LocateRegistry/getRegistry)
"Hello"
(java.rmi.server.UnicastRemoteObject/exportObject
(name-server) 0)))
(register-server)
One last thing, as a note, you don't want to leave a call like (register-server) directly in your code, since that will get called on compilation. commenting that out, or reserving it for the REPL is a better approach.

Why do you write sample codes with main() and output instead of JUnit Tests

I'm new to Stackoverflow and I wonder, why almost everybody writes samplecodes with a static main() and output like here in first answer: some ugly main
from some ugly main:
But what you posted looks like it's just a properties file. Try this:
import java.io.FileInputStream;
import java.util.Properties;
public class Main {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("test.properties"));
System.out.println(properties.getProperty("ReferenceDataLocation"));
System.out.println(properties.getProperty("LicenseKey"));
System.out.println(properties.getProperty("foo"));
}
}
which will print:
as
al
null
wouldn't it be nicer to write it as JUnit Test? It's easier to read. You can verify the result with just CTRL+C + CTRL-V + RunAs -> JUnit and see what is expected (or not).
Am I wrong with this idea?
I would write the main as this:
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import java.io.ByteArrayInputStream;
import java.util.Properties;
import org.junit.Test;
public class TestSomeInputStreamAsProperties {
String someFileAsString =
"ReferenceDataLocation = as\n"+
" \n" +
" \n" +
" ##############################################################################\n" +
" #\n" +
" # LicenseKey\n" +
" # Address Doctor License\n" +
" #\n" +
" ##############################################################################\n" +
" LicenseKey = al\n";
#Test
public void whenReadingFromSomeInputStreamWeShouldGetProperties() throws Exception {
// Arrange
Properties properties = new Properties();
// Act
properties.load(new ByteArrayInputStream(someFileAsString.getBytes()));
// Assert
assertThat(properties.getProperty("ReferenceDataLocation"), is("as"));
assertThat(properties.getProperty("LicenseKey"), is("al"));
assertThat(properties.getProperty("foo"), is(nullValue()));
}
}
The question is: why would I write a sample with main() and output? why don't users try to get on the JUnit train and start writing tests to verify their code?
+
Another Question: why don't people post their problems as JUnit tests?
I'm kinda disappointed.
EDIT: - don't get me wrong about this. It's just expectations > reality ;) I think stackoverflow is still a great site and I will write here all my problems and try to help others to solve theirs. I thought, JUnit is more spread and it would be appreciated by your community to focus on solving problems with JUnit.
Instead I realise that it is not wanted.
Wouldn't you be disappointed too?
Not everybody has JUnit, so a simple program with just main() is more likely to run anywhere.
Seasoned open source developers with experiences in several high profile projects
know, that best chance to get patch approved and integrated is to provide failing unit
test along with fixing patch. But such people are mostly answering questions here - not asking.
So it is task for answerers to promote good asking practices by up/downvoting questions and writing meaningfull comments.
A JUnit test is not an SSCCE in that it is not self contained.
wouldn't it be nicer to write it as JUnit Test?
Not really.
It's easier to read.
Only if you're experienced with that particular unit testing framework. And even then I'd say that it's as easy to read, not easier.
You can verify the result with just CTRL+C + CTRL-V + RunAs -> JUnit and see what is expected (or not).
Only if you're using an IDE and already have a project with that testing framework set up.
Sample code should demonstrate one specific thing and not introduce additional concepts and dependencies.
One (probably the only) advantage of main() is that it's a sort of common least denominator - the code should be understandable and reproducible by anyone, no matter what is their dev environment and favourite testing framework (you can bet some people would have a proprietary one - cause they think JUnit is crap, or dodgy corporate standards or whatever). But if you feel more comfortable with JUnit, just do that - maybe others will like it and start doing the same.
"It's a Free World..."
Good boy and good question. Do not do as a bad boys do! People that run ugly main instead of JUnit or TestNG tests are bad boys! :)

platform-independent /dev/null output sink for Java

Other than an anonymous class (new OutputStream() { ... }), can anyone suggest a moral equivalent of new FileOutputStream("/dev/null") that also works on Windows?
In case someone's wondering 'what's this for?'
I have a program that does a consistency analysis on a file. It has a 'verbose' option. When the verbose option is on, I want to see a lot of output. The program is not in a hurry, it's a tool, so instead of writing all those extra if statements to test if I want the output, I just want to write it to the bit-bucket when not desired.
You can use NullOutputStream from apache commons
https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/output/NullOutputStream.html
Or just implement your own
package mypackage;
import java.io.OutputStream;
import java.io.IOException;
public class NullOutputStream extends OutputStream {
public void write(int i) throws IOException {
//do nothing
}
}
NUL works for Windows NT, but that doesn't work in *NIX.
output = new FileOutputStream("NUL");
Better use NullOutputStream of the Commons IO instead to be platform independent.
Starting from JDK 11, you can use a new static method on OutputStream - nullOutputStream.
var out = OutputStream.nullOutputStream();
As long as you don't care about the slight performance difference (and you don't feel like you might run out of space), you can just use "/dev/null". On Windows, it will create a real file on whatever your current drive is (e.g., c:\dev\null).

Include Perl in Java

Is there any way to execute perl code without having to use Runtime.getRuntime.exec("..."); (parse in java app)?
I've been looking into this myself recently. The most promising thing I've found thus far is the Inline::Java module on CPAN. It allows calling Java from Perl but also (via some included Java classes) calling Perl from Java.
this looks like what you're asking for
Inline::Java provides an embedded Perl interpreter in a class. You can use this to call Perl code from your Java code.
Graciliano M. Passos' PLJava also provides an embedded interpreter.
Don't use JPL (Java Perl Lingo)--the project is dead and has been removed from modern perls.
Inline::Perl is the accepted way. But there's also Jerl which may be run from a JAR.
Here's an example without using the VM wrapper (which is not so fun).
Here's some examples using the jerlWrapper class to make it easier to code:
import jerlWrapper.perlVM;
public final class HelloWorld {
/* keeping it simple */
private static String helloWorldPerl = "print 'Hello World '.$].\"\n\";";
public static void main(String[] args) {
perlVM helloJavaPerl = new perlVM(helloWorldPerl);
helloJavaPerl.run();
}
}
or
import jerlWrapper.perlVM;
public final class TimeTest {
/* The (ugly) way to retrieve time within perl, with all the
* extra addition to make it worth reading afterwards.
*/
private static String testProggie = new String(
"my ($sec, $min, $hr, $day, $mon, $year) = localtime;"+
"printf(\"%02d/%02d/%04d %02d:%02d:%02d\n\", "+
" $mon, $day + 1, 1900 + $year, $hr, $min, $sec);"
);
public static void main(String[] args) {
perlVM helloJavaPerl = new perlVM(testProggie);
boolean isSuccessful = helloJavaPerl.run();
if (isSuccessful) {
System.out.print(helloJavaPerl.getOutput());
}
}
}
I could have sworn it was easy as pie using the Java Scripting API.
But apparently it's not on the list of existing implementations...
So, maybe this helps instead :
java and perl
edit: i said "maybe"
No, I don't believe this exists. While there have been several languages ported to the JVM (JRuby, Jython etc) Perl is not yet one of them.
In the future, the standard way to use any scripting language is through the java Scripting Support introduced in JSR 223. See the scripting project homepage for a list of scripting languages supported at the moment. Unfortunately, Perl isn't on there yet :-(

Calling a java program from another

How do i call a Java command from a stand alone java program.
I understand that Runtime.getRuntime().exec("cmd c/ javac <>.java"); would work. However, this would be platform specific.
Any other APIs available that could make it work in j2sdk1.4 ?
If you can run everything in the same JVM, you could do something like this:
public class Launcher {
...
public static void main(String[] args) throws Exception {
launch(Class.forName(args[0]), programArgs(args, 1));
}
protected static void launch(Class program, String[] args) throws Exception {
Method main = program.getMethod("main", new Class[]{String[].class});
main.invoke(null, new Object[]{args});
}
protected static String[] programArgs(String[] sourceArgs, int n) {
String[] destArgs = new String[sourceArgs.length - n];
System.arraycopy(sourceArgs, n, destArgs, 0, destArgs.length);
return destArgs;
}
And run it with a command line like this:
java Launcher OtherClassWithMainMethod %CMD_LINE_ARGS%
Calling Runtime.getRuntime().exec() is not only platform specific, it is extremely inefficient. It will result in spawning a brand new shell and an entire jvm which could potentially be very expensive depending on the dependencies of this application (no pun intended).
The best way to execute "external" Java code would be to place it in your CLASSPATH. If you must call an application's main method you can simply import and call the method directly. This could be done like so:
import my.externals.SomeMain
// call as if we are running from console
SomeMain.main(new String[] {"some", "console", "arguments"})
Of course, the best case scenario would be to simply use this as an external library and access the code you need without having to call SomeMain.main(). Adhering to best practices and writing proper encapsulated modular objects allows for much greater portability and ease of use when being used by other applications.
When you leave the JVM and move to system commands, then you have to deal with the platform specific commands yourself. The JVM offers a good way for abstraction, so why move away?
If you want to execute java specific binaries, check out the ant libraries of java. You can execute ant scripts from java which execute platform depending commands.
Java programming from quercus php on GAE:
import com.newatlanta.commons.vfs.provider.gae.GaeVFS;
import org.apache.commons.io.IOUtils;
import java.lang.Long;
import java.lang.Boolean;
GaeVFS::setRootPath(quercus_servlet_request()->getSession(true)->getServletContext()->getRealPath('/'));
define('VFSM', GaeVFS::getManager());
//VFSM->resolveFile('gae://gaevfs')->createFolder();
$file=VFSM->resolveFile('gae://gaevfs/tmp1');
//$file->createFile();
$text='pp';
$method=$file->getClass()->getDeclaredMethod('updateContentSize', array(Long::TYPE, Boolean::TYPE));
$method->setAccessible(true);
$method->invoke($file, strlen($text), true);
$out=$file->getContent()->getOutputStream();
IOUtils::write($text, $out, 'UTF8');
$out->close();
$in=$file->getContent()->getInputStream();
$method=$file->getClass()->getDeclaredMethod('doGetContentSize',array());
$method->setAccessible(true);
$len=$method->invoke($file);
$whole=IOUtils::toString($in, 'UTF8').':'.$len."<br>";
$in->close();
echo $whole;
GaeVFS::clearFilesCache();
GaeVFS::close();

Categories

Resources