I am trying to use clojure to implement a "plugin" for some vendor
supplied software.
Here is a little background on the vendor supplied software. It
expects me to implement a particular interface and then put the jar
file containing that implementation into a directory on its server.
Then when a client runs the software, my implemented class gets "sent"
to the client from the server via RMI and then my implementation of
the interface runs on the client. The client doesn't have my jar file
(or the clojure jar file) in it's classpath. Only the server has
those jar files. RMI seems to be smart enough to upload whatever
dependencies are necessary.
I have successfully built a very simple implementation in clojure and
it seems to work. The problem is, I would like to be able to update my
implementation on the client on the fly. I embedded a repl-server in
my class and I can successfully connect to it. Just to be clear, the
repl-server is running on the client and I am able to connect to the
repl getting a prompt "clojure.core=>". However, the repl seems to be
quite crippled. If I enter (+ 1 1) I get the following error:
"java.lang.ClassNotFoundException: clojure.lang.Numbers". If enter
(str "kent") I get "java.lang.NoClassDefFoundError: clojure/lang/
AFunction". Most things I enter produce something similar. I can
however do a simple def such as (def x 3) and x does get defined so
the REPL does seem to be running in some sense.
It seems like it might be a classpath problem, but I'm not sure why my
"compiled" code, running on the client would not have a classpath
problem while the repl, running on the same client cant find core
classes.
Any ideas?
Thanks.
Kent.
First of all, would it be possible to distribute clojure.jar as part of your RMI client? Based on your description of the vendor software, I'm guessing the answer is no.
Second, is the contents of clojure.jar and your RMI object in the same jar file on the server, or are both in their own jar files?
It seems very likely that it's a classloader issue. In Clojure each defined function generates its own class file that Clojure then load via a specific class loader. IIRC each function is loaded by its own classloader instance in order to allow that function to be garbage collected in case it is redefined. Similarly, I think, RMI uses its own class loader to load remote RMI objects over the network. So possibly the two class loaders interact badly.
Sorry I can't be of more help...
-- Lauri
Related
I'd like to use figwheel to reload the frontend of an all-clojure project I'm playing with.
The backend serves a REST api and is organized as a bunch of components from which I create a system in my main function (I use duct to create the handler component). I want to pass state to my handlers using closures, but the only means of configuring figwheel to use my handler seems to be setting the ring-handler key in project.clj, and this requires that I pass a handler that is defined in a namespace at lein startup time.
So - is there a way to configure figwheel when I am doing my component startup? I'm still very new at Closure so it's likely I'm missing something in plain sight.
Passing state as parameter to a ring handler? is a similar question, but the answer there involves binding the handler a var at the top-level of a namespace, which I'm trying to avoid.
Figwheel doesn't need to be a handler. You can wrap a component that autobuilds while your server is up and running by dissecting this code into a component, a dependency to your server component so that it starts first. Note that this isn't officially supported. Running lein figwheel from the shell to boot a seperate JVM is the conventional usage.
If you are using Stuarts component lib I'd recommend to wrapping the ring handler from within a server component rather than via project.clj. Use this project or adapt the code snippet for a jetty component.
Notice that figwheel is devtooling, so in production you most likely want to serve a compiled js file built with e. g. lein-cljsbuild.
James Reeves made a component for figwheel here
Duct-Figwheel-Component
A component for the Figwheel development tool, designed to be used in the Duct framework (but can be used in any component-based system).
Installation
Add the following dependency to your project.clj:
[duct/figwheel-component "0.3.3"]
How can I set it up, so that I can use Light Table on the Mac, connected to a Ubuntu-hosted nREPL, and create a new program/project.clj? Can anybody help me to understand what my approach should be, and where I'm going wrong?
I have a Ubuntu server, in VirtualBox, along with Leiningen, Pedestal, and a pedestal 'helloworld' sample program, that displays in a browser. I just can't connect to the same REPL that runs the helloworld program. I don't have client-side access or control to the server-side object.
I want to do client-server Clojure development from my Mac host LT, creating server-side programs, that I can view in a REPL.
I don't find LT to be intuitive in this area, and the advice I've read only suggests that LT will connect to an existing project/REPL. I want to create new objects, from the client
Assuming you are talking mostly about the server side of things (don't know much yet about ClojureScript), here is how you would setup a new project and code interactively against a remote repl.
lein new project-name in your VM.
Setup your project.clj the way you want it. You must include dependencies!
Start the REPL in your VM and note the port number
Commit your code to version control (git).
Checkout the same codebase for editing in LightTable in Mac OSX.
Connect to the remote REPL.
Open core.clj or create a new namespace file and start hacking.
Evaluate your code snippets or the entire file.
There are a couple of potential problems I foresee with this. First is that whenever you add a dependency, you will need to commit the change to version control, synchronize your VM working copy, restart your REPL, and reconnect LightTable to the remote REPL.
Second, you may have problems as the project grows beyond a few namespaces. I believe if your namespace requires another namespace from your project, the remote REPL process will (I think) try to load it off it's local classpath. If the dependency is not there or has changed, I don't think LightTable is smart enough to send the required namespaces over the wire. Try it out and let us know what the actual behavior is.
I am calling some C++ code that tries to load a Java class, e.g.
JNIEnv *jenv = ...
jclass cls = jenv->FindClass("org/some/bundle/SomeClass");
Now, the problem is that this class resides in an OSGi bundle, and the code above cannot find my class.
This problem only arise when running unit tests (Tycho-surefire headless tests). Is there a simple way to force the OSGi framework to find my class from JNI? On the Java side, I suspect something like Dynamic-ImportPackage could have fixed my problem. I am unwilling to change the third party C++ library just to get it working with the test framework, so I prefer a solution on the Java test setup / configuration side, if possible.
The FindClass method of JNIEnv only searches the contents of the system ClassLoader as defined by the global application classpath. Since OSGi does not use the global classpath, it is no surprise that this doesn't work.
In general whenever loading a class, you need to specify not just the class name but also the classloader that should load it. This is an inevitable requirement of modularity. So your code needs to be able to find the bundle that you expect to contain the class, and then call its loadClass method. You can do this directly in C++ code, but it may be easier to write a Java utility method to do it and then just call that method from C++.
Well, I am not 100% sure that your case is like mine.
In my RCP I used to get the exception:
ClassNotFoundException: com.tool.packageA.IWantToLoadThisClass cannot be found by com.tool.packageB_1.0.0.qualifier
A simple solution was to:
Add com.tool.packageA to com.tool.packageB MANIFEST.MF Require-Bundle.
I though wanted to avoid that solution, because I was able to load other classes found in other packages normally com.tool.packageC, com.tool.packageD (This wasn't done by me though so I didn't know how it worked).
Searching around I came to find the other solution which I ended up using to keep things similar to the current working packages (com.tool.packageC, com.tool.packageD).
The solution was:
Using Eclipse-BuddyPolicy and Eclipse-RegisterBuddy see here for detailed info
This is how to get it to work:
Add Eclipse-BuddyPolicy: registered to com.tool.packageB MANIFEST.MF
Add Eclipse-RegisterBuddy: com.tool.packageB to com.tool.packageA MANIFEST.MF
Add Require-Bundle: com.tool.packageB to com.tool.packageA MANIFEST.MF
Now com.tool.packageA.IWantToLoadThisClass will be visible from com.tool.packageB and you will be able to find it when jenv->FindClass("com/tool/packageA/IWantToLoadThisClass");.
I hope this helps.
I created a logging module which logs messages to a mysql db, the current code is located here:
https://github.com/amiadogroup/mod_log_chat_mysql5/blob/master/src/mod_log_chat_mysql5.erl
The Problem with the current code is, that sometimes the connection gets closed and as a result, the module doesn't work anymore.
As you see in the code, I store the DBRef in an ets table, which is not really the good way to go.
I asked the erlang mailinglist about this and they suggested me to do the DB Connection as an own child process of the module. This would enable the module to gracefully restart the connection upon closing of the connection.
Now my question is: how can I implement this child process with gen_server and/or gen_mod?
Do I need to create two files or can I do it within the same file?
Is there any example somewhere on how I could achieve that?
Edit: As you can see in the linked github repo, I updated the code and it works now, weeha!
Looking at the mod_Archive code helped me a lot, although I didn't decide to upgrade my ejabberd version.
I ran into another, but related problem now. In the code you see that I do an initial query with "SET NAMES UTF8" to prevent garbling of messages. It seems that this isn't done again if the gen_server does a reconnect. Is there any hook I can call upon reconnect so that the UTF8 query is done everytime?
Edit#2:
Now I switched to Emysql (https://github.com/Eonblast/Emysql) and it works out of the box by specifying the encoding directly on connect.
Code is on github.
Thanks for your help,
Michael
I suggest you look into general Erlang/OTP principles (gen_server, supervisor, etc).
ejabberd is relying on this standard Erlang architecture pattern.
Regarding your comment on database, ejabberd has its own way on managing database and passing queries to MySQL for example. You should as well look into it.
In your source code you are only applying the gen_mod behaviour, if you do wish to have a gen_server you can do it in the same module, if you define the gen_server behaviour has well.
A good example would be the ejabberd module mod_archive, which implements both behaviours.
Edit: I never really worked "directly" with mysql on erlang. But through the ejabberd methods I find it pretty "easy"(you will have to make a few setup, but rather easy). You have the method
ejabberd_odbc:sql_query_t(Query)
And has an example you can find it on the module mod_archive_odbc.
To use that method(and the last module) I haved downloaded the mysql native driver and put the beams created from the driver in ejabberd ebin dir (you can put it anywhere has long is on the erlang path).
A a soft link to the ejabberd ebin is my favorite:
ln -s <diryouhavethedriver>/ebin/*.beam /usr/lib/ejabberd/ebin/
and do a few configurations on you ejabberd.cfg. This process is described on this page on process one. Notice that the full steps are to make mysql the full database of ejabberd. You may not want that, so you must jump a few steps.
Hope this help.
I'm trying to understand how cake implements its multiple JVM approach. At a high level, I thought that cake was working similar to nailgun, where there is a single JVM instance (one JVM process), and new "JVMs" for different projects were actually just clojure/jars evaluated in a new classloader (along with different jar dependencies), which in my eyes is not a new JVM instance. From What's the difference between Cake and Leiningen? however, there is an implication that there are multiple JVMs (one for cake, and * for the projects), not just a single JVM instance.
If there are new JVM instances created, where does the speedup come from? With my understanding, I would reason that starting a new JVM implies creating a new JVM process which incurs the same startup overhead as usual.
If there are not, how are native dependencies added on? From what I understand, the JVM only knows about native dependencies from command line arguments passed before runtime. The only way I know how to circumvent this is with a Sun/Oracle JVM implementation specific hack listed below.
(let [clazz java.lang.ClassLoader
field (.getDeclaredField clazz "sys_paths")]
(.setAccessible field true)
(.set field clazz nil)
(System/setProperty "java.library.path" (apply str (interpose ";" native-paths))))
Cake has a Ruby script that starts up and manages the JVMs. Ruby doesn't have the JVM overhead, so the Ruby script could create the JVMs and then when you execute commands, the Ruby script would delegate those commands to the JVMs.
The reason two JVMs was necessary was so that cake's dependencies (the cake JVM) were separate from the project's dependencies (the bake JVM). Some commands like cake repl run in the bake JVM to take advantage of the project's classpath.
However, in the most recent version, there is only a single JVM per project. This is possible using different classloaders in the same JVM. The relevant library used is classlojure.
Even with the two JVM versions, the JVMs were persistent, meaning they were only spawned once and then restarted only when absolutely necessary, like in the case of a changed classpath (when you add a new dependency or something similar). I'm not sure why you'd think this would mean incurring the JVM overhead every time a command is executed. The idea is that a lot of commands happen instantly rather than every command starting a JVM.
Raynes is correct. As of cake 0.6.0, there is one JVM per project. Cake runs in the main classloader and uses classlojure to load the project in a separate classloader and reload it when the classpath changes. We have discussed a global ~/.cake/config option to share a single JVM among all projects. It shouldn't be too hard to add this using classlojure. The main issue with this approach is how to keep cake task plugins separate. Perhaps the global cake project could run in the main classloader and each project could get two classloaders (one for cake and one for the project).
As for native dependencies, classlojure doesn't support adding them after the JVM starts up. A patch to add this functionality would be welcome as long as the native library path is local to a specific classloader and isn't shared among all classloaders in the same JVM.