Access FacesContext in xAgent (in new Thread) - java

I am planning to use single entry point for all 5 minutes xAgents, meaning one XPage launchs all 5 minutes "java agents" (classes that should be launched every 5 minutes). I would like to lauch that java code in new different Threads to have true parallel lauch of such agents.
The mentioned "java agents" have strong interdependency with other NSF app classes. Many of them rely on FacesContext and / or other XSP / JSF global variables.
"Java agent" code example:
import javax.faces.context.FacesContext;
import com.ibm.domino.xsp.module.nsf.NSFComponentModule;
import com.ibm.domino.xsp.module.nsf.NotesContext;
import com.ibm.xsp.extlib.util.ExtLibUtil;
public class Agent1 implements Runnable {
private NSFComponentModule module;
public Agent1() {
this.module = NotesContext.getCurrent().getModule();
System.out.println("Agent1: test 1.1: " + (ExtLibUtil.getCurrentSessionAsSigner() == null)); // FALSE here
System.out.println("Agent1: test 1.2: " + (FacesContext.getCurrentInstance() == null)); // FALSE here
}
public void run() {
NotesContext context = new NotesContext(this.module);
NotesContext.initThread(context);
System.out.println("Agent1: test 2.2: " + (ExtLibUtil.getCurrentSessionAsSigner() == null)); // TRUE here
System.out.println("Agent1: test 2.2: " + (FacesContext.getCurrentInstance() == null)); // TRUE here
// Threaded xAgent job here...
NotesContext.termThread();
}
}
The issue: Such methods like: FacesContext.getCurrentInstance(), ExtLibUtil.getCurrentSessionAsSigner() return NULL in new Thread.
The question: Is it possible to init XSP / JSF engine inside new Thread to get access to FacesContext, etc (to get not null in lines "Agent1: test 2.1" and "Agent1: test 2.2")?
Thanks in advance!

I encountered a similar problem when developing with XOTS in OpenNTF Domino API. The best option is to pass whatever objects are needed in the constructor. Here's the relevant blog post on XOTS http://www.intec.co.uk/xots-background-and-multithreaded-tasks-the-openntf-domino-api-way-part-two/ (replace "two" with "one" and "three" for the other parts of the series).
XOTS works very well for parallel processing and allows configuration of the number of threads, by default 10.
When I looked at documentation for threading in XPages, the blog posts I found suggested potential issues not covered in that post, but didn't elaborate. I've not investigated further.

Related

ScriptEngine clear and dispose

My application uses a ScriptEngine to offer plugin-ability to my end-users.
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
Whenever a user makes changes to his script, then the application replaces the engine instane by a new instance.
String newScript = ...;
engine = engineManager.getEngineByName("nashorn");
engine.eval(newScript);
Two closely related questions:
Should I try to reuse engines and perform some kind of clear() on them ?
If I just replace my engine with a new instance, should I dispose the previous instance in some way, to avoid memory leaks ? (e.g. I can imagine that the user could manage to create a script that starts a thread.)
The problem is, I cannot find any method that looks like a clear() or a dispose(). Does that mean that my current approach is correct ?
You can use a single engine instance but use separate Bindings objects. Bindings acts as a top-level program environment, so if you want to evaluate a script into what is basically a "new global scope" then you could do that. Look into javax.script API docs on how to do this. You can either use ScriptEngine.eval that takes a Bindings as second argument or the one that takes ScriptContext as second argument.
Even if there's no script code surviving from the previous evaluation, you'll save some initialization time as the script engine will already have predefined various JavaScript data-holder classes and property maps ("hidden classes").
Also: yes, everything is garbage collected. There's no need for an explicit "disposal" API.
I just wanted to share what I tested myself. It makes perfect sense, but for those still in doubt: Created threads do continue to run if you just replace engine instances:
public static void main(String[] args) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
String script =
"new java.lang.Thread(function() {\n" +
" for(;;) {" +
" print('Here\\'s Johnny !');" +
" java.lang.Thread.sleep(1000);" +
" }\n" +
"}).start();";
ScriptEngine engine = manager.getEngineByName("nashorn");
try {
engine.eval(script);
} catch (ScriptException e) {
e.printStackTrace();
}
// replace engine
engine = manager.getEngineByName("nashorn");
engine.eval("print('please, make it stop!!!');");
// please collect !!!
System.gc();
}
Output:
Here's Johnny !
please, make it stop!!!
Here's Johnny !
Here's Johnny !
Here's Johnny !
...
I guess that the garbage collector can clean the scripts, but not their actions outside their context. I think created threads are not even linked to the scripts in any way (i.e. outside their scope). So, I think it's just impossible for the jvm to detect or decide that these threads are linked to a replaced script and may or may not be stopped.
But this leads us too far for one stackoverflow question. Let's just focus on the ability to dispose/clear the bindings (i.e. ScriptContext).
Block java threads in nashorn scripts:
A possible solution, is to narrow down the available functionality. Here follow a couple of ways to avoid the creation of threads:
The following disables all java functionality:
// the option -nj is short for --no-java
ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine("-nj");
But you can also disable specific classes, using a ClassFilter.
ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine((className) -> {
if ("java.lang.Thread".equals(className)) return false;
if ("java.lang.Runnable".equals(className)) return false;
if ("java.util.Timer".equals(className)) return false;
if (className.startsWith("java.util.concurrency")) return false;
if (className.startsWith("javafx")) return false;
if (className.startsWith("javax.swing")) return false;
if (className.startsWith("java.awt")) return false;
return true;
});
Note: as soon as you define a ClassFilter also reflection classes are blocked automatically. So, you don't have to block those packages explicitly.

Tool for java that uses annotation to monitor/log/report threads accessing given method?

Context:
I have created a small (java) multithread server for a game. Despite my best efforts of following the best practices it turned out that some methods that were intended to be called from just one thread got called from 2 or more threads. After debugging and analysis I have managed to "fix" my design but I was wondering:
The question:
Is there a tool (or if not - is it possible (and how) to be developed) that allows you to mark some methods with annotations like #SingleThread or #ThreadCount(2) or #ThreadNameLike("my_fancy_thread_group*") which counts/monitors/logs access to these methods like:
#SingleThread - checks if this method is always accessed by only thread
#ThreadCount(2) - is accessed by two threads exactly
#ThreadNameLike - is accessed only by threads with name matching the pattern(s)
The idea is to do a TEST run of the program and get at least log record that annotated condition is violated.
I was thinking that probably AspectJ can do the job to some extend with it's pointcuts but then I realized that some approach similar to Dagger / Dagger2 will be better, i.e. when you want to test your server you will have to turn on an annotation processor (let's called it hypothetically "SafetyFirst") which will generate adapter (wrapper?) classes which contain the monitoring code. Then you will run the server, run some load tests and then check the logs for violations (or in an ideal world - get a report file).
I fully realize that such tool:
will not provide 100% coverage of all potential cases;
will mask/trigger heisenbugs
will slow down the examined program
but at very least it can serve as an early warning system that will clearly advertise violations of the intended design.
I used a similar test with AspectJ load time weaving for intended printing of all function calls within my package.
Best way of load time weaving is you dont dirty your classes like compile time wevaing. When you remove -javaagent:<path to aspectj lib> and your custom astpect lib classpath entry from your run command. Then all all gone, clear.
I made some changes and implemented a test covering #ThreadCount functionality you asked. You need to download and install AspectJ.
Please see code snippets:
aspect Profile {
private static Map<String, AtomicInteger> counterMap = new HashMap<String, AtomicInteger>();
pointcut threadCountPc(test.ThreadCount tc) : execution(* test..*(..)) && #annotation(tc);
Object around(test.ThreadCount tc) : threadCountPc(tc) {
String signature = thisJoinPointStaticPart.getSignature().toString();
AtomicInteger counter = getCounter(signature);
int currentValue = counter.incrementAndGet();
if (currentValue >= tc.value()){
System.out.println("[Thread Name:" + Thread.currentThread().getName() +
"] Method Name:" + signature + ", threadCount:" + currentValue + " exceeds " + tc.value());
}
try{
return proceed(tc);
}finally{
counter.decrementAndGet();
}
}
private static AtomicInteger getCounter(String methodName){
AtomicInteger value = counterMap.get(methodName);
if (value == null){
synchronized (counterMap){
value = counterMap.get(methodName);
if (value == null){
value = new AtomicInteger(0);
counterMap.put(methodName, value);
}
}
}
return value;
}
}
Compiling: "C:/aspectj1.8/bin/ajc.bat" profile_ft.aj -cp C:/aspectj1.8/lib/aspectjrt.jar;../test/. -1.6 -outxml -outjar profile_ft.jar
Running: java -javaagent:C:/aspectj1.8/lib/aspectjweaver.jar -cp aspectj/profile_ft.jar;test test.Test1

Java Jinput: rescan / reload controllers

I am using java jinput library to read data from joypad, and I have trouble reloading Controllers, I use this to load them:
public Controller[] findStickControllers() {
ControllerEnvironment ce =
ControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
System.out.println(cs.length); //test
ArrayList<Controller> sel = new ArrayList<>();
for (Controller c: cs) {
if(c.getType() == Type.STICK) {
sel.add(c);
}
}
return sel.toArray(new Controller[]{});
}
This works fine, but if I disconnect my controller, calling this will find it again, and vice versa (connecting it after the first check will not find it at all).
I have tried to put sleep before the fist lookup, with these results:
Controllers are acctually scanned when this method is called first time (not at start of the program)
When called again, this always returns same controllers as it returned for the first time.
First call will also write warning bellow
Even when controller is connected (and works), then disconnected (it will still find it though) and reconnected, it will not work
Warning from point 3: (didn't format well in the list)
WARNING: Found unknown Windows version: Windows 8
Attempting to use default windows plug-in.
Loading: net.java.games.input.DirectAndRawInputEnvironmentPlugin
I am using Win 8, and had same problem on Win 7. I had also tried this with mouse, same results.
How can I acctually reload controllers for the 2nd, 3rd, and so on time?
I encountered the same problem. The reason is that the actual hardware scan happens only once for each DefaultControllerEnvironment object. Since the only accessible instantiation is a singleton, it never does another scan.
A simple way to force a hardware scan is to create a new object, but neither the class nor the constructor are public. You can however work around this limitation by calling the constructor via reflection.
Rescan
private static ControllerEnvironment createDefaultEnvironment() throws ReflectiveOperationException {
// Find constructor (class is package private, so we can't access it directly)
Constructor<ControllerEnvironment> constructor = (Constructor<ControllerEnvironment>)
Class.forName("net.java.games.input.DefaultControllerEnvironment").getDeclaredConstructors()[0];
// Constructor is package private, so we have to deactivate access control checks
constructor.setAccessible(true);
// Create object with default constructor
return constructor.newInstance();
}
Usage
// Be aware that creating a new environment is fairly expensive
Controller[] controllers = createDefaultEnvironment().getControllers();
Remove Windows 8 Warnings
/**
* Fix windows 8 warnings by defining a working plugin
*/
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
String os = System.getProperty("os.name", "").trim();
if (os.startsWith("Windows 8")) { // 8, 8.1 etc.
// disable default plugin lookup
System.setProperty("jinput.useDefaultPlugin", "false");
// set to same as windows 7 (tested for windows 8 and 8.1)
System.setProperty("net.java.games.input.plugins", "net.java.games.input.DirectAndRawInputEnvironmentPlugin");
}
return null;
}
});
}
If you use the accepted answer, you might want to consider killing the thread that was spawned by the previous environment before setting a new one because it won't be cleaned up otherwise. You can do so by calling something like:
final Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (final Thread thread : threadSet) {
final String name = thread.getClass().getName();
if (name.equals("net.java.games.input.RawInputEventQueue$QueueThread")) {
thread.interrupt();
try {
thread.join();
} catch (final InterruptedException e) {
thread.interrupt();
}
}
}
The warning is because the last time I updated that code windows 7 wasn't even out IIRC, I'll update it.
The controller reload is a feature that has been requested a number of times, but no-one deems it important enough to spend any time implementing it. If you submit a patch I'll take a look and see about committing it. Until someone finds it important enough to spend the time to write it, it's just a missing feature.
I had the same problem before.
I add the rescanning feature (for Windows back-end only) and post the patch on Java gaming forum but no ones seem interested in to integrate it.
So if you need it, apply my patch from here: http://www.java-gaming.org/topics/rescan-controllers/24782/msg/224604/view.html#msg224604

JRuby: Calling Java Code From A Rack App And Keeping It In Memory

I currently know Java and Ruby, but have never used JRuby. I want to use some RAM- and computation-intensive Java code inside a Rack (sinatra) web application. In particular, this Java code loads about 200MB of data into RAM, and provides methods for doing various calculations that use this in-memory data.
I know it is possible to call Java code from Ruby in JRuby, but in my case there is an additional requirement: This Java code would need to be loaded once, kept in memory, and kept available as a shared resource for the sinatra code (which is being triggered by multiple web requests) to call out to.
Questions
Is a setup like this even possible?
What would I need to do to accomplish it? I am not even sure if this is a JRuby question per se, or something that would need to be configured in the web server. I have experience with Passenger and Unicorn/nginx, but not with Java servers, so if this does involve configuration of a Java server such as Tomcat, any info about that would help.
I am really not sure where to even start looking, or if there is a better way to be approaching this problem, so any and all recommendations or relevant links are appreciated.
Yes, a setup it's possibile ( see below about Deployment ) and to accomplish it I would suggest to use a Singleton
Singletons in Jruby
with reference to question: best/most elegant way to share objects between a stack of rack mounted apps/middlewares? I agree with Colin Surprenant's answer, namely singleton-as-module pattern which I prefer over using the singleton mixin
Example
I post here some test code you can use as a proof of concept:
JRuby sinatra side:
#file: sample_app.rb
require 'sinatra/base'
require 'java' #https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
java_import org.rondadev.samples.StatefulCalculator #import you java class here
# singleton-as-module loaded once, kept in memory
module App
module Global extend self
def calc
#calc ||= StatefulCalculator.new
end
end
end
# you could call a method to load data in the statefull java object
App::Global.calc.turn_on
class Sample < Sinatra::Base
get '/' do
"Welcome, calculator register:#{App::Global.calc.display}"
end
get '/add_one' do
"added one to calculator register, new value:#{App::Global.calc.add(1)}"
end
end
You can start it in tomcat with trinidad or simply with rackup config.ru but you need:
#file: config.ru
root = File.dirname(__FILE__) # => "."
require File.join( root, 'sample_app' ) # => true
run Sample # ..in sample_app.rb ..class Sample < Sinatra::Base
something about the Java Side:
package org.rondadev.samples;
public class StatefulCalculator {
private StatelessCalculator calculator;
double register = 0;
public double add(double a) {
register = calculator.add(register, a);
return register;
}
public double display() {
return register;
}
public void clean() {
register = 0;
}
public void turnOff() {
calculator = null;
System.out.println("[StatefulCalculator] Good bye ! ");
}
public void turnOn() {
calculator = new StatelessCalculator();
System.out.println("[StatefulCalculator] Welcome !");
}
}
Please note that the register in here is only a double but in your real code you can have a big data structure in your real scenario
Deployment
You can deploy using Mongrel, Thin (experimental), Webrick (but who would do that?), and even Java-centric application containers like Glassfish, Tomcat, or JBoss. source: jruby deployments
with TorqueBox that is built on the JBoss Application Server.
JBoss AS includes high-performance clustering, caching and messaging functionality.
trinidad is a RubyGem that allows you to run any Rack based applet wrap within an embedded Apache Tomcat container
Thread synchronization
Sinatra will use Mutex#synchronize method to place a lock on every request to avoid race conditions among threads. If your sinatra app is multithreaded and not thread safe, or any gems you use is not thread safe, you would want to do set :lock, true so that only one request is processed at a given time. .. Otherwise by default lock is false, which means the synchronize would yield to the block directly.
source: https://github.com/zhengjia/sinatra-explained/blob/master/app/tutorial_2/tutorial_2.md
Here are some instructions for how to deploy a sinatra app to Tomcat.
The java code can be loaded once and reused if you keep a reference to the java instances you have loaded. You can keep a reference from a global variable in ruby.
One thing to be aware of is that the java library you are using may not be thread safe. If you are running your ruby code in tomact, multiple requests can execute concurrently, and those requests may all access your shared java library. If your library is not thread safe, you will have to use some sort of synchronization to prevent multiple threads accessing it.

is it possible to block calls to System.exit through ConditionalPermissionAdmin?

The documentation is not helping at all, OSGi in Action does not have an example head to toes on how to do things. For example, I want bundle A to deny a package import from Bundle B, etc. Simple examples, from start to end - I can't find them.
But back to my question, I want to block calls to System.exit for obvious reasons, besides "do not implement your own Security Manager", I did not get much from the Virgo forum, thus my question here.
EDIT
Since I want this to happen in Virgo, here is what I have tried:
public void start(BundleContext context) throws Exception {
System.out.println("===== Starting Bundle PermissionsTest =====");
SecurityManager securityManager = System.getSecurityManager();
if(securityManager == null) throw new IllegalArgumentException("Security Manager is not defined!");
ServiceReference serviceReference =
(ServiceReference) context.getServiceReference(ConditionalPermissionAdmin.class.getName());
if(serviceReference == null) throw new IllegalArgumentException(ConditionalPermissionAdmin.class.getName() + " IS NULL");
else System.out.println("===== Good so far 1 =====");
ConditionalPermissionAdmin conditionalPermissionAdmin =
(ConditionalPermissionAdmin)context.getService(serviceReference);
if(conditionalPermissionAdmin == null) throw new IllegalArgumentException("ConditionalPermissionAdmin can not be found");
else System.out.println("===== Good so far 2 =====");
What I did first in Virgo ie enable the Equinox Security Manager (because this is the one Virgo uses). The specification of the OSGi says that each container has to implement it's own Security Manager extended with a bunch of OSGi specific actions.
In case of Virgo this is Equinox Security Manager. Enabling it is pretty easy - just add two lines in bin/dmk.sh and thus you have it.
Ok, so I do have the ConditionalPermissionAdmin - good! Now, I can for example, add a Security Check, like, BundlePermission say for a Bundle. Sure, but that happens for bundle specific actions, like start/stop/export, etc etc. I can't seem to figure out how to do it for a LifeCycle action - System.exit in my case.
btw, I use version 4.2.0 of the osgi-core, and nope I can't upgrade to 4.3.0, at least not now.
System.exit is governed by RuntimePermission( "exitVm", "<>"), so the example syntax in the spec gives
DENY {
( java.lang.RuntimePermission "exitVm" "*" )
}
In Java code (haven't tested it, so beware):
ConditionalPermissionInfo info = admin.newConditionalPermissionInfo(
"name",
null,
new PermissionInfo[] { new PermissionInfo(
"java.lang.RuntimePermission", "exitVm", "*") },
ConditionalPermissionInfo.DENY
);
ConditionalPermissionUpdate update = admin
.newConditionalPermissionUpdate();
update.getConditionalPermissionInfos().add(0, info);
update.commit();
The subject is rather well treated in the book "OSGi in Action". Please remember that the primary audience of the specification was the implementer of the specification, not the end user. The members were supposed to provide the educational material to bridge that gap. Later specs tried to become more educational for end-users.

Categories