SlideShare a Scribd company logo
RelProxy
Easy Class Reload
and Scripting with Java
Jose María Arranz Santamaría January 28, 2015
RelProxy...
● WHAT IS?
● WHY?
● HOW IT WORKS…
● WHERE?
WHAT IS?
What is?
● A simple Java and Groovy automatic class reloader
from source
o In development … and production if you want
● Converts pure Java on the fastest scripting language
o Compiling on demand, not a new language like BeanShell
o Including an interactive shell
WHY?
ENVY!!!
Why?
● Envy of Groovy’s “false” scripting
● Groovy is NOT really a scripting/interpreted language, it
“just” compiles on the fly to conventional Java bytecode
o More correctly Groovy is a dynamic language
● I realized this when making an example of embedding
Groovy on ItsNat web framework
Why?
● Envy for automatic class reload of other web
frameworks & dynamic langs with just a page reload
● Auto context reloading (Tomcat etc) is TEDIOUS
o Everything is reloaded per file save => slowing all and PermGen
o Session is lost, start again and again
● ItsNat, a Java based web framework, asked his father
for support of automatic class reloading
o It suffers of “me too” syndrome
o Very soon I realized it could be an independent project
HOW IT WORKS
How it works
● The Java Reload Proxy
● A shell scripting language named Java
● JSR-223 Java Scripting API
● Bonus: Groovy loves Java. The Groovy Reload Proxy
The Java Reload Proxy
The Java Reload Proxy
GOAL:
Automatic recompile and reload changed source
files/classes in web with a simple page reload
WITHOUT CONTEXT RELOADING!!
DISABLE IT!! => read the Manual
The Java Reload Proxy
InvocationHandler
VersionedObject Object
JProxyEngine
Change
Detector And
Compiler
Class
Reloader
java.lang.ref
lect.Proxy
public
method
invoked
ask
reload
needed
reload
JProxyClass
Loader
new
instance
versioned
method
called
The Java Reload Proxy
● Advantages over JVM HotSwap in Debug
o JVM standard HotSwap is limited to change method bodies
 RelProxy/JProxy gives you more freedom, even add new classes
● Advantages over Context Reloading
o Context Reloading reloads ANYTHING
 RelProxy only loads a subset of your code
o In CR session is lost
o In CR, in practice, reloading happens per file save
The Java Reload Proxy
● Everything cannot and should not be reloaded
o Server state must be kept when source code is changed
o Reloading data hold by singletons is dangerous
● Stateless/functional classes are candidates for
reloading
o In ItsNat, code doing page load/event rendering on request, that is
code dependent from ItsNatServletRequestListener
o The method
public void processRequest(ItsNatServletRequest request,ItsNatServletResponse response)
o is called on page load time
The Java Reload Proxy
package example.javaex;
import org.itsnat.core.event.ItsNatServletRequestListener;
import org.itsnat.core.ItsNatServletRequest;
import org.itsnat.core.ItsNatServletResponse;
import org.itsnat.core.html.ItsNatHTMLDocument;
public class JProxyExampleLoadListener implements ItsNatServletRequestListener
{
protected FalseDB db;
public JProxyExampleLoadListener() { }
public JProxyExampleLoadListener(FalseDB db) { this.db = db; }
public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response)
{
System.out.println("JProxyExampleLoadListener 1 " + this.getClass().getClassLoader().hashCode());
new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db);
}
}
The Java Reload Proxy
FalseDB db = new FalseDB();
String pathPrefix = context.getRealPath("/") + "/WEB-INF/jproxyex/pages/";
ItsNatDocumentTemplate docTemplate;
docTemplate = itsNatServlet.registerItsNatDocumentTemplate("jproxyex","text/html",
pathPrefix + "jproxyex.html");
ItsNatServletRequestListener listener = new example.javaex.JProxyExampleLoadListener(db);
docTemplate.addItsNatServletRequestListener(listener);
● In a conventional ItsNat web application,
JProxyExampleLoadListener is a singleton
registered with something like this:
The Java Reload Proxy
public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response)
{
System.out.println("JProxyExampleLoadListener 10 " + this.getClass().getClassLoader().hashCode());
new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db);
}
● Remember the JProxyExampleLoadListener code:
● If we are able of reloading JProxyExampleLoadListener we are also able to fully reload
JProxyExampleDocument and dependent code on a page load =>VIEW LOGIC RELOADED
Every page reload
creates a new instance
The Java Reload Proxy
Because JProxyExampleLoadListener is a singleton
we can reload the code => fields must not change (state)
Q) How can we detect source code changes of the
singleton class and related classes and apply them in real
time?
A) Registering a proxy instead of the original singleton,
when a method is called, it is performed on the proxy
instead of the original Java object => reload classes
This is why com.innowhere.relproxy.jproxy.JProxy exists
The Java Reload Proxy
package example.javaex;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import javax.servlet.*;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import org.itsnat.core.event.ItsNatServletRequestListener;
import org.itsnat.core.http.HttpServletWrapper;
● Configuration in the servlet
o Part of this code can be put in a ServletContextListener
The Java Reload Proxy
import org.itsnat.core.tmpl.ItsNatDocumentTemplate;
import com.innowhere.relproxy.RelProxyOnReloadListener;
import com.innowhere.relproxy.jproxy.*;
public class JProxyExampleServlet extends HttpServletWrapper
{
public JProxyExampleServlet() { }
@Override
public void init(ServletConfig config) throws ServletException
{
super.init(config);
ServletContext context = getServletContext();
String realPath = context.getRealPath("/");
String inputPath = realPath + "/WEB-INF/javaex/code/";
String classFolder = null; // Optional: context.getRealPath("/") + "/WEB-INF/classes";
Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});
long scanPeriod = 300;
JProxy config params
Java sources to reload
are here!!
The Java Reload Proxy
RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() {
@Override
public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) {
System.out.println("Reloaded " + objNew + " Calling method: " + method);
}
};
JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener() {
@Override
public boolean isExcluded(File file, File rootFolderOfSources) { return false; }
};
JProxyCompilerListener compilerListener = new JProxyCompilerListener(){
@Override
public void beforeCompile(File file) { System.out.println("Before compile: " + file); }
@Override
public void afterCompile(File file) { System.out.println("After compile: " + file); }
};
Listener monitor of class
reloading
Listener monitor of file
compiling
Filter for excluding files
of reloading
The Java Reload Proxy
JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() {
@Override
public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) {
List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
int i = 1;
for (Diagnostic<? extends JavaFileObject> diagnostic : diagList) {
System.err.println("Diagnostic " + i);
System.err.println(" code: " + diagnostic.getCode());
System.err.println(" kind: " + diagnostic.getKind());
System.err.println(" line number: " + diagnostic.getLineNumber());
System.err.println(" column number: " + diagnostic.getColumnNumber());
System.err.println(" start position: " + diagnostic.getStartPosition());
System.err.println(" position: " + diagnostic.getPosition());
System.err.println(" end position: " + diagnostic.getEndPosition());
System.err.println(" source: " + diagnostic.getSource());
System.err.println(" message: " + diagnostic.getMessage(null));
i++;
}
}
};
The Java Reload Proxy
JProxyConfig jpConfig = JProxy.createJProxyConfig();
jpConfig.setEnabled(true)
.setRelProxyOnReloadListener(proxyListener)
.setInputPath(inputPath)
.setJProxyInputSourceFileExcludedListener(excludedListener)
.setScanPeriod(scanPeriod)
.setClassFolder(classFolder)
.setCompilationOptions(compilationOptions)
.setJProxyCompilerListener(compilerListener)
.setJProxyDiagnosticsListener(diagnosticsListener);
JProxy.init(jpConfig);
Configuring JProxy library
Efective configuration
The Java Reload Proxy
String pathPrefix = context.getRealPath("/") + "/WEB-INF/javaex/pages/";
ItsNatDocumentTemplate docTemplate;
docTemplate = itsNatServlet.registerItsNatDocumentTemplate("javaex","text/html",
pathPrefix + "javaex.html");
FalseDB db = new FalseDB();
ItsNatServletRequestListener listener = JProxy.create(
new example.javaex.JProxyExampleLoadListener(db),ItsNatServletRequestListener.class);
docTemplate.addItsNatServletRequestListener(listener);
}
}
Registers ItsNat HTML
template
Proxy creation wrapping
the load listener singleton
Registering the load listener
singleton associated to the
template
The Java Reload Proxy
● FalseDB and related are not reloaded in this example
o It is not proxied and is an external dependency
● Just calling setEnabled(false) in production and
performance impact is ZERO
● JProxy is ItsNat agnostic
o In spite of previous example is based on ItsNat
● JProxy can be used in similar use cases in your Java
project
o Web or not web
WHO THE FUCK
IS USING
ITSNAT !!!
https://groups.google.com/forum/#!topic/itsnat/CO8Qd-Am3L0
How JProxy can help you
in development time,
a GWT example
YES…
GWT !!
How JProxy can help you in
development time, a GWT example
● We can define normal Java source code folders as
reloadable
o No need of source code below WEB-INF/
o No need to publish source code in production
o Of course this is NOT valid for production
● We will show this feature through a GWT-RPC example
● Download and install Eclipse (Luna is supposed) and
Google Plugin for Eclipse
● Create a GWT-RPC project
o Select New/Other/Google/Web Application Project
o Add relproxy-x.y.z.jar to WEB-INF/lib
How JProxy can help you in
development time, a GWT example
● Structure generated
o Name/package relproxy_ex_gwt/com.innowhere.relproxyexgwt
relproxy_ex_gwt (root folder of project)
src/com/innowhere/relproxyexgwt
client
GreetingService.java
GreetingServiceAsync.java
Relproxy_ex_gwt.java
server
GreetingServiceImpl.java
shared
FieldVerifier.java
Relproxy_ex_gwt.gwt.xml
How JProxy can help you in
development time, a GWT example
● We are only be able to reload classes executed in server
o Classes below server/ folder
o That is, the servlet GreetingServiceImpl.java
● Initial code of GreetingServiceImpl
package com.innowhere.relproxyexgwt.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.innowhere.relproxyexgwt.client.GreetingService;
import com.innowhere.relproxyexgwt.shared.FieldVerifier;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
How JProxy can help you in
development time, a GWT example
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
// If the input is not valid, throw an IllegalArgumentException back to
// the client.
throw new IllegalArgumentException("Name must be at least 4 characters long");
}
String serverInfo = getServletContext().getServerInfo();
String userAgent = getThreadLocalRequest().getHeader("User-Agent");
// Escape data from the client to avoid cross-site script vulnerabilities.
input = escapeHtml(input);
userAgent = escapeHtml(userAgent);
return "Hello, " + input + "!<br><br>I am running " + serverInfo +
".<br><br>It looks like you are using:<br>" + userAgent;
}
How JProxy can help you in
development time, a GWT example
/**
* Escape an html string. Escaping data received from the client helps to
* prevent cross-site script vulnerabilities.
*
* @param html the html string to escape
* @return the escaped string
*/
private String escapeHtml(String html) {
if (html == null) {
return null;
}
return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
}
}
● Converted to use JProxy...
How JProxy can help you in
development time, a GWT example
package com.innowhere.relproxyexgwt.server;
import java.io.File;
import java.lang.reflect.Method;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.tools.*;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.innowhere.relproxy.RelProxyOnReloadListener;
import com.innowhere.relproxy.jproxy.*;
import com.innowhere.relproxyexgwt.client.GreetingService;
/**
* The server-side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
How JProxy can help you in
development time, a GWT example
protected GreetingServiceDelegate delegate;
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletContext context = config.getServletContext();
String inputPath = context.getRealPath("/") + "/../src/";
JProxyInputSourceFileExcludedListener excludedListener =
new JProxyInputSourceFileExcludedListener() {
@Override
public boolean isExcluded(File file, File rootFolder) {
String absPath = file.getAbsolutePath();
if (file.isDirectory()) return absPath.endsWith(File.separatorChar + "client") ||
absPath.endsWith(File.separatorChar + "shared");
else return absPath.endsWith(GreetingServiceDelegate.class.getSimpleName() + ".java") ||
absPath.endsWith(GreetingServiceImpl.class.getSimpleName() + ".java");
}
};
Your source !!
Folders excluded
Concrete files excluded
How JProxy can help you in
development time, a GWT example
String classFolder = null; // Optional: context.getRealPath("/") + "/WEB-INF/classes";
Iterable<String> compilationOptions =
Arrays.asList(new String[]{"-source","1.6","-target","1.6"});
long scanPeriod = 300;
RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() {
public void onReload(Object objOld,Object objNew,Object proxy,Method method,Object[] args){
System.out.println("Reloaded " + objNew + " Calling method: " + method);
}
};
JProxyCompilerListener compilerListener = new JProxyCompilerListener(){
public void beforeCompile(File file) {
System.out.println("Before compile: " + file);
}
public void afterCompile(File file) {
System.out.println("After compile: " + file);
}
};
How JProxy can help you in
development time, a GWT example
JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() {
public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) {
List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
int i = 1;
for (Diagnostic diagnostic : diagList) {
System.err.println("Diagnostic " + i);
System.err.println(" code: " + diagnostic.getCode());
System.err.println(" kind: " + diagnostic.getKind());
System.err.println(" line number: " + diagnostic.getLineNumber());
System.err.println(" column number: " + diagnostic.getColumnNumber());
System.err.println(" start position: " + diagnostic.getStartPosition());
System.err.println(" position: " + diagnostic.getPosition());
System.err.println(" end position: " + diagnostic.getEndPosition());
System.err.println(" source: " + diagnostic.getSource());
System.err.println(" message: " + diagnostic.getMessage(null));
i++;
}
}
};
How JProxy can help you in
development time, a GWT example
JProxyConfig jpConfig = JProxy.createJProxyConfig();
jpConfig.setEnabled(true)
.setRelProxyOnReloadListener(proxyListener)
.setInputPath(inputPath)
.setJProxyInputSourceFileExcludedListener(excludedListener)
.setScanPeriod(scanPeriod)
.setClassFolder(classFolder)
.setCompilationOptions(compilationOptions)
.setJProxyCompilerListener(compilerListener)
.setJProxyDiagnosticsListener(diagnosticsListener);
JProxy.init(jpConfig);
this.delegate = JProxy.create(
new GreetingServiceDelegateImpl(this),GreetingServiceDelegate.class);
} // init
How JProxy can help you in
development time, a GWT example
public String greetServer(String input) throws IllegalArgumentException {
try {
return delegate.greetServer(input);
}
catch(IllegalArgumentException ex) {
ex.printStackTrace();
throw ex;
}
catch(Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
public HttpServletRequest getThreadLocalRequestPublic() {
return getThreadLocalRequest();
}
}
How JProxy can help you in
development time, a GWT example
● GreetingServiceImpl is a servlet, therefore a
singleton in practice, we cannot reload this singleton
● This is why we have moved the code to
GreetingServiceDelegateImpl
o implementing the interface GreetingServiceDelegate
● This new delegation singleton is registered on JProxy
and can be reloaded
this.delegate = JProxy.create(
new GreetingServiceDelegateImpl(this),GreetingServiceDelegate.class);
How JProxy can help you in
development time, a GWT example
● When a source change is detected JProxy needs to
reload dependent classes in a new class loader
● But the servlet GreetingServiceImpl cannot be
reloaded, neither client and shared classes, nor
GreetingServiceDelegate => EXCLUDED
public boolean isExcluded(File file, File rootFolder) {
String absPath = file.getAbsolutePath();
if (file.isDirectory()) return absPath.endsWith(File.separatorChar + "client") ||
absPath.endsWith(File.separatorChar + "shared");
else return absPath.endsWith(GreetingServiceDelegate.class.getSimpleName() + ".java") ||
absPath.endsWith(GreetingServiceImpl.class.getSimpleName() + ".java");
}
How JProxy can help you in
development time, a GWT example
● GreetingServiceDelegateImpl is basically the
same as the original servlet generated
package com.innowhere.relproxyexgwt.server;
import com.innowhere.relproxyexgwt.shared.FieldVerifier;
public class GreetingServiceDelegateImpl implements GreetingServiceDelegate
{
protected GreetingServiceImpl parent;
public GreetingServiceDelegateImpl() { } // Needed by JProxy
public GreetingServiceDelegateImpl(GreetingServiceImpl parent) {
this.parent = parent;
}
How JProxy can help you in
development time, a GWT example
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
throw new IllegalArgumentException("Name must be at least 4 characters long");
}
String serverInfo = parent.getServletContext().getServerInfo();
String userAgent = parent.getThreadLocalRequestPublic().getHeader("User-Agent");
input = escapeHtml(input);
userAgent = escapeHtml(userAgent);
return "Hello, " + input + "!<br><br>I am running " + serverInfo
+ ".<br><br>It looks like you are using:<br>" + userAgent;
}
private String escapeHtml(String html) {
if (html == null) { return null; }
return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");
}
}
How JProxy can help you in
development time, a GWT example
● Run this example
o Run As / Web Application / GWT Super Dev Mode
● Open http://127.0.0.1:8888/Relproxy_ex_gwt.html
How JProxy can help you in
development time, a GWT example
How JProxy can help you in
development time, a GWT example
● Click on the “Close” button
● Modify in Eclipse GreetingServiceDelegateImpl
o just change "Hello" by "Hello <b>BROTHER</b>" and save:
return "Hello <b>BROTHER</b>, " + input + "!<br><br>I am running " + serverInfo
+ ".<br><br>It looks like you are using:<br>" + userAgent;
● Click again on “Send to Server” button
o The RPC callback will be called
o In this example a page reload is not needed
How JProxy can help you in
development time, a GWT example
A shell scripting
language named Java
A shell scripting lang named Java
● Your JDK includes a built-in API for compiling Java files
o Since Java 1.6
o The compiler API used by web app servers to compile servlets and
JSPs when changed (previously generated as servlet)
● RelProxy includes a script named jproxysh to execute
Java from source code
o Supported Windows and Unixes
● To execute code like this:
(file example_java_shell)
#!/usr/bin/env jproxysh
String msg = args[0] + args[1];
System.out.println(msg);
System.out.println("example_java_shell 1 ");
example.javashellex.JProxyShellExample.exec();
A shell scripting lang named Java
● Obviously Java code is the code in main method
● jproxysh must be in PATH
● JAVA_HOME and CLASSPATH standard environment
variables must be defined
o CLASSPATH must include relproxy-X.Y.jar
● This is the expected hierarchy in this example
<root_folder>
example_java_shell (file)
example (folder)
javashellex (folder)
JProxyShellExample.java (file)
A shell scripting lang named Java
● Configuration options are defined by using environment
variables
● Example:
export JAVA_OPTS="-client -Xmx100m"
export JPROXYSH_CACHE_CLASS_FOLDER="/tmp/java_shell_test_classes"
export JPROXYSH_COMPILATION_OPTIONS="-source 1.6 -target 1.6"
./example_java_shell "HELLO " "WORLD!"
Not really needed (just an ex.)
To avoid recompiling (optional)
A shell scripting lang named Java
● Nothings prevents of executing a complete root class
o File example_java_shell_complete_class
#!/usr/bin/env jproxysh
import example.javashellex.JProxyShellExample;
public class example_java_shell_complete_class {
public static void main(String[] args) {
String msg = args[0] + args[1];
System.out.println(msg);
System.out.println("example_java_shell_complete_class 1 ");
JProxyShellExample.exec();
}
}
A shell scripting lang named Java
● Of course a conventional root class is valid
o Yes you can execute a conventional Java program from source code!!
jproxysh $PROJECT/code/example_normal_class.java "HELLO " "WORLD!"
● Or just a code snippet
jproxysh -c 'System.out.print("This code snippet says: ");' 
'System.out.println("Hello World!!");'
● Or just start an interactive shell
jproxysh
JSR-223
Java Scripting API
JSR-223 Java Scripting API
● Yes RelProxy provides an implementation of JSR-223
API for a scripting language named “Java” or “FuckYou”
JProxyConfig jpConfig = ...;
JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create();
ScriptEngineManager manager = new ScriptEngineManager();
manager.registerEngineName("Java", factory);
manager.getBindings().put("msg","HELLO GLOBAL WORLD!");
ScriptEngine engine = manager.getEngineByName("Java");
((JProxyScriptEngine)engine).init(jpConfig);
try
{
Bindings bindings = engine.createBindings();
bindings.put("msg","HELLO ENGINE SCOPE WORLD!");
StringBuilder code = new StringBuilder();
JProxyScriptEngine
has the same API as
JProxy + eval(...)
JSR-223 Java Scripting API
code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); n");
code.append( " String msg = (String)bindings.get("msg"); n");
code.append( " System.out.println(msg); n");
code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); n");
code.append( " msg = (String)bindings.get("msg"); n");
code.append( " System.out.println(msg); n");
code.append( " example.javashellex.JProxyShellExample.exec(engine); n");
code.append( " return "SUCCESS";");
String result = (String)engine.eval( code.toString() , bindings);
System.out.println(result);
}
catch(ScriptException ex) { ex.printStackTrace(); }
finally
{
((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined
}
The Groovy Reload
Proxy
Err...
Another day...
THANKS &
ENJOY !!
https://github.com/jmarranz/relproxy/
https://github.com/jmarranz/relproxy_examples/
Q & A
I’m sorry, half the world uses this stolen image from…(?)

More Related Content

What's hot

Java 10, Java 11 and beyond
Java 10, Java 11 and beyondJava 10, Java 11 and beyond
Java 10, Java 11 and beyond
Rafael Winterhalter
 
SyScan 2016 - Remote code execution via Java native deserialization
SyScan 2016 - Remote code execution via Java native deserializationSyScan 2016 - Remote code execution via Java native deserialization
SyScan 2016 - Remote code execution via Java native deserialization
David Jorm
 
Size of in java
Size of in javaSize of in java
Size of in java
lorban
 
Android Unit Test
Android Unit TestAndroid Unit Test
Android Unit Test
Phuoc Bui
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
Tobias Lindaaker
 
Mastering Mock Objects - Advanced Unit Testing for Java
Mastering Mock Objects - Advanced Unit Testing for JavaMastering Mock Objects - Advanced Unit Testing for Java
Mastering Mock Objects - Advanced Unit Testing for Java
Denilson Nastacio
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassJava Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug Class
CODE WHITE GmbH
 
The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agents
Rafael Winterhalter
 
Serialization & De-serialization in Java
Serialization & De-serialization in JavaSerialization & De-serialization in Java
Serialization & De-serialization in Java
InnovationM
 
Exploring lambdas and invokedynamic for embedded systems
Exploring lambdas and invokedynamic for embedded systemsExploring lambdas and invokedynamic for embedded systems
Exploring lambdas and invokedynamic for embedded systems
InfinIT - Innovationsnetværket for it
 
Java 9 features
Java 9 featuresJava 9 features
Java 9 features
shrinath97
 
Black Hat EU 2010 - Attacking Java Serialized Communication
Black Hat EU 2010 - Attacking Java Serialized CommunicationBlack Hat EU 2010 - Attacking Java Serialized Communication
Black Hat EU 2010 - Attacking Java Serialized Communication
msaindane
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Christian Schneider
 
Java and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystemJava and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystem
Rafael Winterhalter
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
CODE WHITE GmbH
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
Naresh Jain
 
Spring Certification Questions
Spring Certification QuestionsSpring Certification Questions
Spring Certification Questions
SpringMockExams
 
Fixing the Java Serialization Mess
Fixing the Java Serialization Mess Fixing the Java Serialization Mess
Fixing the Java Serialization Mess
Salesforce Engineering
 
Java Course 6: Introduction to Agile
Java Course 6: Introduction to AgileJava Course 6: Introduction to Agile
Java Course 6: Introduction to Agile
Anton Keks
 

What's hot (20)

Invoke dynamics
Invoke dynamicsInvoke dynamics
Invoke dynamics
 
Java 10, Java 11 and beyond
Java 10, Java 11 and beyondJava 10, Java 11 and beyond
Java 10, Java 11 and beyond
 
SyScan 2016 - Remote code execution via Java native deserialization
SyScan 2016 - Remote code execution via Java native deserializationSyScan 2016 - Remote code execution via Java native deserialization
SyScan 2016 - Remote code execution via Java native deserialization
 
Size of in java
Size of in javaSize of in java
Size of in java
 
Android Unit Test
Android Unit TestAndroid Unit Test
Android Unit Test
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
 
Mastering Mock Objects - Advanced Unit Testing for Java
Mastering Mock Objects - Advanced Unit Testing for JavaMastering Mock Objects - Advanced Unit Testing for Java
Mastering Mock Objects - Advanced Unit Testing for Java
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug ClassJava Deserialization Vulnerabilities - The Forgotten Bug Class
Java Deserialization Vulnerabilities - The Forgotten Bug Class
 
The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agents
 
Serialization & De-serialization in Java
Serialization & De-serialization in JavaSerialization & De-serialization in Java
Serialization & De-serialization in Java
 
Exploring lambdas and invokedynamic for embedded systems
Exploring lambdas and invokedynamic for embedded systemsExploring lambdas and invokedynamic for embedded systems
Exploring lambdas and invokedynamic for embedded systems
 
Java 9 features
Java 9 featuresJava 9 features
Java 9 features
 
Black Hat EU 2010 - Attacking Java Serialized Communication
Black Hat EU 2010 - Attacking Java Serialized CommunicationBlack Hat EU 2010 - Attacking Java Serialized Communication
Black Hat EU 2010 - Attacking Java Serialized Communication
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
 
Java and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystemJava and OpenJDK: disecting the ecosystem
Java and OpenJDK: disecting the ecosystem
 
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
Java Deserialization Vulnerabilities - The Forgotten Bug Class (RuhrSec Edition)
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Spring Certification Questions
Spring Certification QuestionsSpring Certification Questions
Spring Certification Questions
 
Fixing the Java Serialization Mess
Fixing the Java Serialization Mess Fixing the Java Serialization Mess
Fixing the Java Serialization Mess
 
Java Course 6: Introduction to Agile
Java Course 6: Introduction to AgileJava Course 6: Introduction to Agile
Java Course 6: Introduction to Agile
 

Similar to RelProxy, Easy Class Reload and Scripting with Java

Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
Jeff Durta
 
SMI - Introduction to Java
SMI - Introduction to JavaSMI - Introduction to Java
SMI - Introduction to Java
SMIJava
 
How to run java program without IDE
How to run java program without IDEHow to run java program without IDE
How to run java program without IDE
Shweta Oza
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
Jeff Durta
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
Talha Ocakçı
 
Java notes
Java notesJava notes
Java notes
Debasish Biswas
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
Jady Yang
 
Java introduction
Java introductionJava introduction
Java introduction
The icfai university jaipur
 
Unit of competency
Unit of competencyUnit of competency
Unit of competency
loidasacueza
 
Shiksharth com java_topics
Shiksharth com java_topicsShiksharth com java_topics
Shiksharth com java_topics
Rajesh Verma
 
Unit 1 of java part 2 basic introduction
Unit 1 of java part 2 basic introduction Unit 1 of java part 2 basic introduction
Unit 1 of java part 2 basic introduction
AKR Education
 
Viva file
Viva fileViva file
Viva file
anupamasingh87
 
Core Java
Core JavaCore Java
Core Java
Prakash Dimmita
 
The java server pages
The java server pagesThe java server pages
The java server pages
Atul Saurabh
 
Java Enterprise Edition
Java Enterprise EditionJava Enterprise Edition
Java Enterprise Edition
Francesco Nolano
 
Json generation
Json generationJson generation
Json generation
Aravindharamanan S
 
Java questions with answers
Java questions with answersJava questions with answers
Java questions with answers
Kuntal Bhowmick
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for selenium
apoorvams
 
JSR 168 Portal - Overview
JSR 168 Portal - OverviewJSR 168 Portal - Overview
JSR 168 Portal - Overview
Vinay Kumar
 

Similar to RelProxy, Easy Class Reload and Scripting with Java (20)

Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
SMI - Introduction to Java
SMI - Introduction to JavaSMI - Introduction to Java
SMI - Introduction to Java
 
How to run java program without IDE
How to run java program without IDEHow to run java program without IDE
How to run java program without IDE
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 
Java notes
Java notesJava notes
Java notes
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
 
Java introduction
Java introductionJava introduction
Java introduction
 
Unit of competency
Unit of competencyUnit of competency
Unit of competency
 
Shiksharth com java_topics
Shiksharth com java_topicsShiksharth com java_topics
Shiksharth com java_topics
 
Unit 1 of java part 2 basic introduction
Unit 1 of java part 2 basic introduction Unit 1 of java part 2 basic introduction
Unit 1 of java part 2 basic introduction
 
Viva file
Viva fileViva file
Viva file
 
Core Java
Core JavaCore Java
Core Java
 
The java server pages
The java server pagesThe java server pages
The java server pages
 
Java Enterprise Edition
Java Enterprise EditionJava Enterprise Edition
Java Enterprise Edition
 
Json generation
Json generationJson generation
Json generation
 
Java questions with answers
Java questions with answersJava questions with answers
Java questions with answers
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for selenium
 
1_JavIntro
1_JavIntro1_JavIntro
1_JavIntro
 
JSR 168 Portal - Overview
JSR 168 Portal - OverviewJSR 168 Portal - Overview
JSR 168 Portal - Overview
 

Recently uploaded

Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
NaapbooksPrivateLimi
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Hivelance Technology
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
KrzysztofKkol1
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 

Recently uploaded (20)

Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 

RelProxy, Easy Class Reload and Scripting with Java

  • 1. RelProxy Easy Class Reload and Scripting with Java Jose María Arranz Santamaría January 28, 2015
  • 2. RelProxy... ● WHAT IS? ● WHY? ● HOW IT WORKS… ● WHERE?
  • 4. What is? ● A simple Java and Groovy automatic class reloader from source o In development … and production if you want ● Converts pure Java on the fastest scripting language o Compiling on demand, not a new language like BeanShell o Including an interactive shell
  • 7. Why? ● Envy of Groovy’s “false” scripting ● Groovy is NOT really a scripting/interpreted language, it “just” compiles on the fly to conventional Java bytecode o More correctly Groovy is a dynamic language ● I realized this when making an example of embedding Groovy on ItsNat web framework
  • 8. Why? ● Envy for automatic class reload of other web frameworks & dynamic langs with just a page reload ● Auto context reloading (Tomcat etc) is TEDIOUS o Everything is reloaded per file save => slowing all and PermGen o Session is lost, start again and again ● ItsNat, a Java based web framework, asked his father for support of automatic class reloading o It suffers of “me too” syndrome o Very soon I realized it could be an independent project
  • 10. How it works ● The Java Reload Proxy ● A shell scripting language named Java ● JSR-223 Java Scripting API ● Bonus: Groovy loves Java. The Groovy Reload Proxy
  • 12. The Java Reload Proxy GOAL: Automatic recompile and reload changed source files/classes in web with a simple page reload WITHOUT CONTEXT RELOADING!! DISABLE IT!! => read the Manual
  • 13. The Java Reload Proxy InvocationHandler VersionedObject Object JProxyEngine Change Detector And Compiler Class Reloader java.lang.ref lect.Proxy public method invoked ask reload needed reload JProxyClass Loader new instance versioned method called
  • 14. The Java Reload Proxy ● Advantages over JVM HotSwap in Debug o JVM standard HotSwap is limited to change method bodies  RelProxy/JProxy gives you more freedom, even add new classes ● Advantages over Context Reloading o Context Reloading reloads ANYTHING  RelProxy only loads a subset of your code o In CR session is lost o In CR, in practice, reloading happens per file save
  • 15. The Java Reload Proxy ● Everything cannot and should not be reloaded o Server state must be kept when source code is changed o Reloading data hold by singletons is dangerous ● Stateless/functional classes are candidates for reloading o In ItsNat, code doing page load/event rendering on request, that is code dependent from ItsNatServletRequestListener o The method public void processRequest(ItsNatServletRequest request,ItsNatServletResponse response) o is called on page load time
  • 16. The Java Reload Proxy package example.javaex; import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.ItsNatServletRequest; import org.itsnat.core.ItsNatServletResponse; import org.itsnat.core.html.ItsNatHTMLDocument; public class JProxyExampleLoadListener implements ItsNatServletRequestListener { protected FalseDB db; public JProxyExampleLoadListener() { } public JProxyExampleLoadListener(FalseDB db) { this.db = db; } public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response) { System.out.println("JProxyExampleLoadListener 1 " + this.getClass().getClassLoader().hashCode()); new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db); } }
  • 17. The Java Reload Proxy FalseDB db = new FalseDB(); String pathPrefix = context.getRealPath("/") + "/WEB-INF/jproxyex/pages/"; ItsNatDocumentTemplate docTemplate; docTemplate = itsNatServlet.registerItsNatDocumentTemplate("jproxyex","text/html", pathPrefix + "jproxyex.html"); ItsNatServletRequestListener listener = new example.javaex.JProxyExampleLoadListener(db); docTemplate.addItsNatServletRequestListener(listener); ● In a conventional ItsNat web application, JProxyExampleLoadListener is a singleton registered with something like this:
  • 18. The Java Reload Proxy public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response) { System.out.println("JProxyExampleLoadListener 10 " + this.getClass().getClassLoader().hashCode()); new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db); } ● Remember the JProxyExampleLoadListener code: ● If we are able of reloading JProxyExampleLoadListener we are also able to fully reload JProxyExampleDocument and dependent code on a page load =>VIEW LOGIC RELOADED Every page reload creates a new instance
  • 19. The Java Reload Proxy Because JProxyExampleLoadListener is a singleton we can reload the code => fields must not change (state) Q) How can we detect source code changes of the singleton class and related classes and apply them in real time? A) Registering a proxy instead of the original singleton, when a method is called, it is performed on the proxy instead of the original Java object => reload classes This is why com.innowhere.relproxy.jproxy.JProxy exists
  • 20. The Java Reload Proxy package example.javaex; import java.io.File; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import javax.servlet.*; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.http.HttpServletWrapper; ● Configuration in the servlet o Part of this code can be put in a ServletContextListener
  • 21. The Java Reload Proxy import org.itsnat.core.tmpl.ItsNatDocumentTemplate; import com.innowhere.relproxy.RelProxyOnReloadListener; import com.innowhere.relproxy.jproxy.*; public class JProxyExampleServlet extends HttpServletWrapper { public JProxyExampleServlet() { } @Override public void init(ServletConfig config) throws ServletException { super.init(config); ServletContext context = getServletContext(); String realPath = context.getRealPath("/"); String inputPath = realPath + "/WEB-INF/javaex/code/"; String classFolder = null; // Optional: context.getRealPath("/") + "/WEB-INF/classes"; Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); long scanPeriod = 300; JProxy config params Java sources to reload are here!!
  • 22. The Java Reload Proxy RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { @Override public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { System.out.println("Reloaded " + objNew + " Calling method: " + method); } }; JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener() { @Override public boolean isExcluded(File file, File rootFolderOfSources) { return false; } }; JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ @Override public void beforeCompile(File file) { System.out.println("Before compile: " + file); } @Override public void afterCompile(File file) { System.out.println("After compile: " + file); } }; Listener monitor of class reloading Listener monitor of file compiling Filter for excluding files of reloading
  • 23. The Java Reload Proxy JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() { @Override public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) { List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics(); int i = 1; for (Diagnostic<? extends JavaFileObject> diagnostic : diagList) { System.err.println("Diagnostic " + i); System.err.println(" code: " + diagnostic.getCode()); System.err.println(" kind: " + diagnostic.getKind()); System.err.println(" line number: " + diagnostic.getLineNumber()); System.err.println(" column number: " + diagnostic.getColumnNumber()); System.err.println(" start position: " + diagnostic.getStartPosition()); System.err.println(" position: " + diagnostic.getPosition()); System.err.println(" end position: " + diagnostic.getEndPosition()); System.err.println(" source: " + diagnostic.getSource()); System.err.println(" message: " + diagnostic.getMessage(null)); i++; } } };
  • 24. The Java Reload Proxy JProxyConfig jpConfig = JProxy.createJProxyConfig(); jpConfig.setEnabled(true) .setRelProxyOnReloadListener(proxyListener) .setInputPath(inputPath) .setJProxyInputSourceFileExcludedListener(excludedListener) .setScanPeriod(scanPeriod) .setClassFolder(classFolder) .setCompilationOptions(compilationOptions) .setJProxyCompilerListener(compilerListener) .setJProxyDiagnosticsListener(diagnosticsListener); JProxy.init(jpConfig); Configuring JProxy library Efective configuration
  • 25. The Java Reload Proxy String pathPrefix = context.getRealPath("/") + "/WEB-INF/javaex/pages/"; ItsNatDocumentTemplate docTemplate; docTemplate = itsNatServlet.registerItsNatDocumentTemplate("javaex","text/html", pathPrefix + "javaex.html"); FalseDB db = new FalseDB(); ItsNatServletRequestListener listener = JProxy.create( new example.javaex.JProxyExampleLoadListener(db),ItsNatServletRequestListener.class); docTemplate.addItsNatServletRequestListener(listener); } } Registers ItsNat HTML template Proxy creation wrapping the load listener singleton Registering the load listener singleton associated to the template
  • 26. The Java Reload Proxy ● FalseDB and related are not reloaded in this example o It is not proxied and is an external dependency ● Just calling setEnabled(false) in production and performance impact is ZERO ● JProxy is ItsNat agnostic o In spite of previous example is based on ItsNat ● JProxy can be used in similar use cases in your Java project o Web or not web
  • 27. WHO THE FUCK IS USING ITSNAT !!!
  • 29. How JProxy can help you in development time, a GWT example
  • 31. How JProxy can help you in development time, a GWT example ● We can define normal Java source code folders as reloadable o No need of source code below WEB-INF/ o No need to publish source code in production o Of course this is NOT valid for production ● We will show this feature through a GWT-RPC example ● Download and install Eclipse (Luna is supposed) and Google Plugin for Eclipse ● Create a GWT-RPC project o Select New/Other/Google/Web Application Project o Add relproxy-x.y.z.jar to WEB-INF/lib
  • 32. How JProxy can help you in development time, a GWT example ● Structure generated o Name/package relproxy_ex_gwt/com.innowhere.relproxyexgwt relproxy_ex_gwt (root folder of project) src/com/innowhere/relproxyexgwt client GreetingService.java GreetingServiceAsync.java Relproxy_ex_gwt.java server GreetingServiceImpl.java shared FieldVerifier.java Relproxy_ex_gwt.gwt.xml
  • 33. How JProxy can help you in development time, a GWT example ● We are only be able to reload classes executed in server o Classes below server/ folder o That is, the servlet GreetingServiceImpl.java ● Initial code of GreetingServiceImpl package com.innowhere.relproxyexgwt.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.innowhere.relproxyexgwt.client.GreetingService; import com.innowhere.relproxyexgwt.shared.FieldVerifier; /** * The server side implementation of the RPC service. */ @SuppressWarnings("serial") public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
  • 34. How JProxy can help you in development time, a GWT example public String greetServer(String input) throws IllegalArgumentException { // Verify that the input is valid. if (!FieldVerifier.isValidName(input)) { // If the input is not valid, throw an IllegalArgumentException back to // the client. throw new IllegalArgumentException("Name must be at least 4 characters long"); } String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); // Escape data from the client to avoid cross-site script vulnerabilities. input = escapeHtml(input); userAgent = escapeHtml(userAgent); return "Hello, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; }
  • 35. How JProxy can help you in development time, a GWT example /** * Escape an html string. Escaping data received from the client helps to * prevent cross-site script vulnerabilities. * * @param html the html string to escape * @return the escaped string */ private String escapeHtml(String html) { if (html == null) { return null; } return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"); } } ● Converted to use JProxy...
  • 36. How JProxy can help you in development time, a GWT example package com.innowhere.relproxyexgwt.server; import java.io.File; import java.lang.reflect.Method; import java.util.*; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.tools.*; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.innowhere.relproxy.RelProxyOnReloadListener; import com.innowhere.relproxy.jproxy.*; import com.innowhere.relproxyexgwt.client.GreetingService; /** * The server-side implementation of the RPC service. */ @SuppressWarnings("serial") public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
  • 37. How JProxy can help you in development time, a GWT example protected GreetingServiceDelegate delegate; public void init(ServletConfig config) throws ServletException { super.init(config); ServletContext context = config.getServletContext(); String inputPath = context.getRealPath("/") + "/../src/"; JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener() { @Override public boolean isExcluded(File file, File rootFolder) { String absPath = file.getAbsolutePath(); if (file.isDirectory()) return absPath.endsWith(File.separatorChar + "client") || absPath.endsWith(File.separatorChar + "shared"); else return absPath.endsWith(GreetingServiceDelegate.class.getSimpleName() + ".java") || absPath.endsWith(GreetingServiceImpl.class.getSimpleName() + ".java"); } }; Your source !! Folders excluded Concrete files excluded
  • 38. How JProxy can help you in development time, a GWT example String classFolder = null; // Optional: context.getRealPath("/") + "/WEB-INF/classes"; Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); long scanPeriod = 300; RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { public void onReload(Object objOld,Object objNew,Object proxy,Method method,Object[] args){ System.out.println("Reloaded " + objNew + " Calling method: " + method); } }; JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ public void beforeCompile(File file) { System.out.println("Before compile: " + file); } public void afterCompile(File file) { System.out.println("After compile: " + file); } };
  • 39. How JProxy can help you in development time, a GWT example JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() { public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) { List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics(); int i = 1; for (Diagnostic diagnostic : diagList) { System.err.println("Diagnostic " + i); System.err.println(" code: " + diagnostic.getCode()); System.err.println(" kind: " + diagnostic.getKind()); System.err.println(" line number: " + diagnostic.getLineNumber()); System.err.println(" column number: " + diagnostic.getColumnNumber()); System.err.println(" start position: " + diagnostic.getStartPosition()); System.err.println(" position: " + diagnostic.getPosition()); System.err.println(" end position: " + diagnostic.getEndPosition()); System.err.println(" source: " + diagnostic.getSource()); System.err.println(" message: " + diagnostic.getMessage(null)); i++; } } };
  • 40. How JProxy can help you in development time, a GWT example JProxyConfig jpConfig = JProxy.createJProxyConfig(); jpConfig.setEnabled(true) .setRelProxyOnReloadListener(proxyListener) .setInputPath(inputPath) .setJProxyInputSourceFileExcludedListener(excludedListener) .setScanPeriod(scanPeriod) .setClassFolder(classFolder) .setCompilationOptions(compilationOptions) .setJProxyCompilerListener(compilerListener) .setJProxyDiagnosticsListener(diagnosticsListener); JProxy.init(jpConfig); this.delegate = JProxy.create( new GreetingServiceDelegateImpl(this),GreetingServiceDelegate.class); } // init
  • 41. How JProxy can help you in development time, a GWT example public String greetServer(String input) throws IllegalArgumentException { try { return delegate.greetServer(input); } catch(IllegalArgumentException ex) { ex.printStackTrace(); throw ex; } catch(Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } } public HttpServletRequest getThreadLocalRequestPublic() { return getThreadLocalRequest(); } }
  • 42. How JProxy can help you in development time, a GWT example ● GreetingServiceImpl is a servlet, therefore a singleton in practice, we cannot reload this singleton ● This is why we have moved the code to GreetingServiceDelegateImpl o implementing the interface GreetingServiceDelegate ● This new delegation singleton is registered on JProxy and can be reloaded this.delegate = JProxy.create( new GreetingServiceDelegateImpl(this),GreetingServiceDelegate.class);
  • 43. How JProxy can help you in development time, a GWT example ● When a source change is detected JProxy needs to reload dependent classes in a new class loader ● But the servlet GreetingServiceImpl cannot be reloaded, neither client and shared classes, nor GreetingServiceDelegate => EXCLUDED public boolean isExcluded(File file, File rootFolder) { String absPath = file.getAbsolutePath(); if (file.isDirectory()) return absPath.endsWith(File.separatorChar + "client") || absPath.endsWith(File.separatorChar + "shared"); else return absPath.endsWith(GreetingServiceDelegate.class.getSimpleName() + ".java") || absPath.endsWith(GreetingServiceImpl.class.getSimpleName() + ".java"); }
  • 44. How JProxy can help you in development time, a GWT example ● GreetingServiceDelegateImpl is basically the same as the original servlet generated package com.innowhere.relproxyexgwt.server; import com.innowhere.relproxyexgwt.shared.FieldVerifier; public class GreetingServiceDelegateImpl implements GreetingServiceDelegate { protected GreetingServiceImpl parent; public GreetingServiceDelegateImpl() { } // Needed by JProxy public GreetingServiceDelegateImpl(GreetingServiceImpl parent) { this.parent = parent; }
  • 45. How JProxy can help you in development time, a GWT example public String greetServer(String input) throws IllegalArgumentException { // Verify that the input is valid. if (!FieldVerifier.isValidName(input)) { throw new IllegalArgumentException("Name must be at least 4 characters long"); } String serverInfo = parent.getServletContext().getServerInfo(); String userAgent = parent.getThreadLocalRequestPublic().getHeader("User-Agent"); input = escapeHtml(input); userAgent = escapeHtml(userAgent); return "Hello, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; } private String escapeHtml(String html) { if (html == null) { return null; } return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;") .replaceAll(">", "&gt;"); } }
  • 46. How JProxy can help you in development time, a GWT example ● Run this example o Run As / Web Application / GWT Super Dev Mode ● Open http://127.0.0.1:8888/Relproxy_ex_gwt.html
  • 47. How JProxy can help you in development time, a GWT example
  • 48. How JProxy can help you in development time, a GWT example ● Click on the “Close” button ● Modify in Eclipse GreetingServiceDelegateImpl o just change "Hello" by "Hello <b>BROTHER</b>" and save: return "Hello <b>BROTHER</b>, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; ● Click again on “Send to Server” button o The RPC callback will be called o In this example a page reload is not needed
  • 49. How JProxy can help you in development time, a GWT example
  • 51. A shell scripting lang named Java ● Your JDK includes a built-in API for compiling Java files o Since Java 1.6 o The compiler API used by web app servers to compile servlets and JSPs when changed (previously generated as servlet) ● RelProxy includes a script named jproxysh to execute Java from source code o Supported Windows and Unixes ● To execute code like this: (file example_java_shell) #!/usr/bin/env jproxysh String msg = args[0] + args[1]; System.out.println(msg); System.out.println("example_java_shell 1 "); example.javashellex.JProxyShellExample.exec();
  • 52. A shell scripting lang named Java ● Obviously Java code is the code in main method ● jproxysh must be in PATH ● JAVA_HOME and CLASSPATH standard environment variables must be defined o CLASSPATH must include relproxy-X.Y.jar ● This is the expected hierarchy in this example <root_folder> example_java_shell (file) example (folder) javashellex (folder) JProxyShellExample.java (file)
  • 53. A shell scripting lang named Java ● Configuration options are defined by using environment variables ● Example: export JAVA_OPTS="-client -Xmx100m" export JPROXYSH_CACHE_CLASS_FOLDER="/tmp/java_shell_test_classes" export JPROXYSH_COMPILATION_OPTIONS="-source 1.6 -target 1.6" ./example_java_shell "HELLO " "WORLD!" Not really needed (just an ex.) To avoid recompiling (optional)
  • 54. A shell scripting lang named Java ● Nothings prevents of executing a complete root class o File example_java_shell_complete_class #!/usr/bin/env jproxysh import example.javashellex.JProxyShellExample; public class example_java_shell_complete_class { public static void main(String[] args) { String msg = args[0] + args[1]; System.out.println(msg); System.out.println("example_java_shell_complete_class 1 "); JProxyShellExample.exec(); } }
  • 55. A shell scripting lang named Java ● Of course a conventional root class is valid o Yes you can execute a conventional Java program from source code!! jproxysh $PROJECT/code/example_normal_class.java "HELLO " "WORLD!" ● Or just a code snippet jproxysh -c 'System.out.print("This code snippet says: ");' 'System.out.println("Hello World!!");' ● Or just start an interactive shell jproxysh
  • 57. JSR-223 Java Scripting API ● Yes RelProxy provides an implementation of JSR-223 API for a scripting language named “Java” or “FuckYou” JProxyConfig jpConfig = ...; JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create(); ScriptEngineManager manager = new ScriptEngineManager(); manager.registerEngineName("Java", factory); manager.getBindings().put("msg","HELLO GLOBAL WORLD!"); ScriptEngine engine = manager.getEngineByName("Java"); ((JProxyScriptEngine)engine).init(jpConfig); try { Bindings bindings = engine.createBindings(); bindings.put("msg","HELLO ENGINE SCOPE WORLD!"); StringBuilder code = new StringBuilder(); JProxyScriptEngine has the same API as JProxy + eval(...)
  • 58. JSR-223 Java Scripting API code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); n"); code.append( " String msg = (String)bindings.get("msg"); n"); code.append( " System.out.println(msg); n"); code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); n"); code.append( " msg = (String)bindings.get("msg"); n"); code.append( " System.out.println(msg); n"); code.append( " example.javashellex.JProxyShellExample.exec(engine); n"); code.append( " return "SUCCESS";"); String result = (String)engine.eval( code.toString() , bindings); System.out.println(result); } catch(ScriptException ex) { ex.printStackTrace(); } finally { ((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined }
  • 62. Q & A I’m sorry, half the world uses this stolen image from…(?)

Editor's Notes

  1. El código fuente está copiado y pegado del Manual de referencia por eso está “coloreado”