SlideShare a Scribd company logo
1 of 52
NetBeans Plugin Development:
  JRebel Experience Report
         JavaOne SF 2012
whoami

Anton Arhipov
JRebel Product Lead

@antonarhipov
anton@zeroturnaround.com
Agenda
• JRebel intro
    – Plugin requirements
•   NetBeans plugin development
•   Integrating with NetBeans server adaptors
•   Integrating with NetBeans debugger
•   Packaging & publishing
ENTER JREBEL
The Turnaround Cycle

            Make
           changes

                         AVG 2.5 min

                      Build,
Observe
                     deploy,
 results
                       wait
Make changes
                                                 in IDE
                    ClassLoader
Framework



              MyObject.class
               Code
               101000101
                                  New code
                                                JRebel
               100010010
                                  111000100
                                  101010010



            MyObject
                                     Configuration
                                  (XML, annotations,..)
in action
Why IDE plugin?

 Usability
Automation
 Debugger
JRebel Plugin for NetBeans

           Workbench      Settings, UX




                                         JRebel Plugin
NetBeans




             Process
                            VM args
            Launcher
                          Breakpoints
            Debugger
                           Stepping
ENTER NETBEANS
PLUGINS
Books
UI Elements
•   Buttons/Actions
•   Toolbars/Menus
•   Settings/Options
•   Popups
•   etc
layers.xml
<folder name="Actions">
  <folder name="JRebel">
     <file name="JRebelToggleAction.instance">
       <attr name="delegate"
             newvalue="o.z.j.n.JRebelToggleAction"/>
     </file>
  </folder>
</folder>

<folder name="Toolbars">
  <folder name="Build">
     <file name="JRebelToggleAction.shadow">
        <attr name="originalFile"
              stringvalue="Actions/JRebel/JRebelToggleAction.instance"/>
        <attr name="position" intvalue="250"/>
Options
Options (Old API)
<folder name="OptionsDialog">
  <file name="JRebelOptions.instance">
    <attr name="instanceCreate"
          methodvalue="o.n.s.o.OptionsCategory.createCategory"/>
    <attr name="controller"
          newvalue="o.z.j.n.JRebelOptionsPanelController"/>
  </file>
</folder>

<folder name="Services">
  <file name="org-zeroturnaround-jrebel-netbeans-options.settings"
        url="options.xml"/>
</folder>
Options (New API)
@OptionsPanelController.SubRegistration(
 location = "Advanced",
 displayName = "#AdvancedOption_DisplayName_Super",
 keywords = "#AdvancedOption_Keywords_Super",
 keywordsCategory = "Advanced/Super")

@org.openide.util.NbBundle.Messages(
  {"AdvancedOption_DisplayName_Super=Super",
   "AdvancedOption_Keywords_Super=super"})

public final class SuperOptionsPanelController
                                   extends OptionsPanelController {
CUSTOM JVM
ARGUMENTS
JVM arguments
• JRebel is bootstrapped using JVM arguments:
               -javaagent:/path/to/jrebel.jar

 -noverify -Xbootclasspath/p:jrebel-bootstrap.jar;jrebel.jar

        -Drebel.log=true -Drebel.jersey_plugin=true

• Various NetBeans project types pass JVM
  arguments slightly differently:
              Web project VS Maven project
               JBoss VS Tomcat VS Glassfish
Server settings: Tomcat

                      Can put your
                     arguments here
Server settings: Glassfish

                          No VM
                        arguments?
Project Deployment




Aha!!
Toggle




Simplest, from the user’s point of view: should not
  care about project type of runtime differences
Toggle
public final class JRebelToggleAction extends BooleanStateAction {
    public void initialize() {
       super.initialize();
       setBooleanState(JRebelSettings.isEnabled());
    }

    public void actionPerformed(ActionEvent ev) {
      super.actionPerformed(ev);
      JRebelSettings.setEnabled(getBooleanState());
     // NbPreferences.forModule(JRebelSettings.class)
     //                .putBoolean(“enabled”, true);

    }
}
Challenge
              No extension points provided
               by the NetBeans platform


                   Load-Time Weaving of
                  NetBeans platform classes


Might not be the brightest bulb idea, but seems to work fine 
PATCHING THE
PLATFORM
org.openide.modules.ModuleInstall
public class Installer extends ModuleInstall {
 @Override
 public void restored() {
    // patch platform classes here

    }
}
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                        .lookup(ClassLoader.class);
Object o = ClassLoader#findLoadedClass(classToPatch )

ClassPool cp = new ClassPool();
cp.appendClassPath(new LoaderClassPath(cl));
CtClass ctc = cp.get(classToPatch);
patch(cp, ctc);
ctc.toClass(cl, null);
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                        .lookup(ClassLoader.class);
                           e.g.
Object o = ClassLoader#findLoadedClass(classToPatch )
     “org.netbeans.modules.glassfish.common.StartTask”
“org.netbeans.modules.tomcat5.ide.StartTomcat$StartRunnable”
ClassPool cp = new ClassPool();
                            etc
cp.appendClassPath(new LoaderClassPath(cl));
CtClass ctc = cp.get(classToPatch);
patch(cp, ctc);
ctc.toClass(cl, null);
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                        .lookup(ClassLoader.class);
Object o = ClassLoader#findLoadedClass(classToPatch )
            a class loader capable for finding
ClassPool cp = new ClassPool(); module
                 resources from any
cp.appendClassPath(new LoaderClassPath(cl));
CtClass ctc = cp.get(classToPatch);
patch(cp, ctc);
ctc.toClass(cl, null);
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                        .lookup(ClassLoader.class);
Object o = ClassLoader#findLoadedClass(classToPatch )

ClassPool= ClassLoader.class
Method m cp = new ClassPool();
cp.appendClassPath(new LoaderClassPath(cl));
        .getDeclaredMethod("findLoadedClass", String.class);
CtClass ctc = cp.get(classToPatch);
m.setAccessible(true);
patch(cp, ctc);
Object o = m.invoke(cl, patchedClassName);
ctc.toClass(cl, null);
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                  Enter Javassist
                        .lookup(ClassLoader.class);
Object o = ClassLoader#findLoadedClass(classToPatch )

ClassPool cp = new ClassPool();
cp.appendClassPath(new LoaderClassPath(cl));
CtClass ctc = cp.get(classToPatch);
patch(cp, ctc);
ctc.toClass(cl, null);
Patcher
String classToPatch = …
ClassLoader cl = Lookup.getDefault()
                        .lookup(ClassLoader.class);
Object o = ClassLoader#findLoadedClass(classToPatch )

ClassPool cp = new ClassPool();
cp.appendClassPath(new LoaderClassPath(cl));
CtClass ctc = cp.get(classToPatch);
                                 This is where patching
patch(cp, ctc);
                                     happens really
ctc.toClass(cl, null);
patch(…)
final CtMethod method = ctc.getDeclaredMethod("run");

method.instrument(new ExprEditor() {
  public void edit(MethodCall m) {
    if ("getJavaOpts".equals(m.getMethodName())) {
      m.replace(
         "if (command == CommandType.START)" +
            OPTS + "$_ = opts + $proceed($$);");
    }
  }
});
patch(…)
final CtMethod method = ctc.getDeclaredMethod("run");

method.instrument(new ExprEditor() {
  public void edit(MethodCall m) {
                                     Patching
    if ("getJavaOpts".equals(m.getMethodName())) {
                        StartTomcat$StartRunnable#run()
      m.replace(
                               for Tomcat launcher
         "if (command == CommandType.START)" +
            OPTS + "$_ = opts + $proceed($$);");
    }
  }
});
patch(…)
final CtMethod method = ctc.getDeclaredMethod("run");

method.instrument(new ExprEditor() {
  public void edit(MethodCall m) {
    if ("getJavaOpts".equals(m.getMethodName())) {
      m.replace(
         "if (command == CommandType.START)" +
            OPTS + "$_ =Should+append custom options
                         opts $proceed($$);");
    }                       to getJavaOpts result
  }
});
patch(…)
    final CtMethod method = ctc.getDeclaredMethod("run");
String OPTS =
"ClassLoader cl = (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class);" +
     method.instrument(new ExprEditor() {
"Class locator = cl.loadClass("org.zeroturnaround.jrebel.netbeans.JRebelLocator");" +
        public void edit(MethodCall m) {
"Method getJRebelOptsStr = locator.getMethod("getJRebelOptsStr", null);" +
           if ("getJavaOpts".equals(m.getMethodName())) {
"String opts = (String) getJRebelOptsStr.invoke(null, null);";
             m.replace(
                "if (command == CommandType.START)" +
                    OPTS + "$_ = opts + $proceed($$);");
           }
        }
     });
patch(…)
    final CtMethod method = ctc.getDeclaredMethod("run");
String OPTS =
"ClassLoader cl = (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class);" +
     method.instrument(new ExprEditor() {
"Class locator = cl.loadClass("org.zeroturnaround.jrebel.netbeans.JRebelLocator");" +
        public void edit(MethodCall m) {
"Method getJRebelOptsStr = locator.getMethod("getJRebelOptsStr", null);" +
           if ("getJavaOpts".equals(m.getMethodName())) {
"String opts = (String) getJRebelOptsStr.invoke(null, null);";
             m.replace(
                "if (command == CommandType.START)" +
                    OPTS + "$_ = opts + $proceed($$);");
           }
            -javaagent:/path/to/jrebel.jar etc
        }
     });
Pros & Cons
+ Can get stuff done even if the platform doesn’t
provide a proper interface

- Brittle for maintenance
New API (7.2)
• SPI for JVM options passed to SE program or
  EE server (Bug 206196)
@StartupArgumentsProvider.Registration(
  position=10, displayName="#DESC_JRebel",
 startMode={StartMode.NORMAL, StartMode.DEBUG})

public class MyArgsProvider
                  implements StartupArgumentsProvider {
@Override
public List<String> getArguments(ServerInstance instance,
                                 StartMode mode)
Dude, where’s my car breakpoint?

DEBUGGER
INTEGRATION
Breakpoints




Line 11: initial breakpoint
Breakpoints




Line 14: same breakpoint,
         but new version of the class

Need to “transfer” the breakpoint
from original class to versioned class
Patching
• o.n.m.d.jpda.breakpoints.LineBreakpointImpl
  – setRequests
  – getLocations
New API (7.3)
    • Allow to provide additional binary classes to
      submit breakpoints on (Bug 215680)

@BreakpointClassFilter.Registration
public class MyFilter extends BreakpointClassFilter {

    @Override
    public ClassNames filterClassNames(ClassNames classNames,
                                   JPDABreakpoint breakpoint){}

}
RELEASING THE PLUGIN
Packaging
Packaging

           Plugin has to be signed


               Module descriptor



   JRebel distribution
                Dependencies

                     Plugin itself
Maven Build
• NetBeans modules maven plugin
  – nbm-maven-plugin
• Properties maven plugin
  – properties-maven-plugin
• Maven dependency plugin
  – maven-dependency-plugin
• Maven compiler plugin
• Maven JAR plugin
Publishing
• http://plugins.netbeans.org/
• Verification is performed manually (by
  volunteers)
• Main criteria: should not break the platform
• Takes some time
Lessons Learned
• UX is hard
• Follow the logic of the target IDE
• Follow the new APIs
• Annotations over layer.xml
• If no required extension point provided, can
  get around with patching via ModuleInstall
• Publishing is not 100% predictable process
Credits
• Big thanks to NetBeans team for awesome co-
  operation & providing the new API for
  debugger and server adaptors!

More Related Content

What's hot

Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)Alok Kumar
 
Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4jeresig
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Kiyotaka Oku
 
Student management system
Student management systemStudent management system
Student management systemgeetika goyal
 
Google Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG NantesGoogle Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG Nantesmikaelbarbero
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
A clean(er) architecture
A clean(er) architectureA clean(er) architecture
A clean(er) architectureAndreaMaglie
 
Testing javascriptwithjasmine sydjs
Testing javascriptwithjasmine sydjsTesting javascriptwithjasmine sydjs
Testing javascriptwithjasmine sydjsJo Cranford
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeletonIram Ramrajkar
 
Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012Anton Arhipov
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Oliver Klee
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheeltcurdt
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical FileSoumya Behera
 
Stored Procedures and MUMPS for DivConq
 Stored Procedures and  MUMPS for DivConq  Stored Procedures and  MUMPS for DivConq
Stored Procedures and MUMPS for DivConq eTimeline, LLC
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6Fiyaz Hasan
 
Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicNew Relic
 

What's hot (20)

Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)
 
Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4Testing, Performance Analysis, and jQuery 1.4
Testing, Performance Analysis, and jQuery 1.4
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介
 
Student management system
Student management systemStudent management system
Student management system
 
Google Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG NantesGoogle Guava & EMF @ GTUG Nantes
Google Guava & EMF @ GTUG Nantes
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
A clean(er) architecture
A clean(er) architectureA clean(er) architecture
A clean(er) architecture
 
Testing javascriptwithjasmine sydjs
Testing javascriptwithjasmine sydjsTesting javascriptwithjasmine sydjs
Testing javascriptwithjasmine sydjs
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
 
Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)Test-driven development for TYPO3 (T3DD11)
Test-driven development for TYPO3 (T3DD11)
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 
Jason parsing
Jason parsingJason parsing
Jason parsing
 
Stored Procedures and MUMPS for DivConq
 Stored Procedures and  MUMPS for DivConq  Stored Procedures and  MUMPS for DivConq
Stored Procedures and MUMPS for DivConq
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6
 
Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
 
Ad java prac sol set
Ad java prac sol setAd java prac sol set
Ad java prac sol set
 

Viewers also liked

Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Improve your Developer Experiece using the WAS Liberty Profile with JRebel Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Improve your Developer Experiece using the WAS Liberty Profile with JRebel Anton Arhipov
 
import continuous.delivery.*
import continuous.delivery.*import continuous.delivery.*
import continuous.delivery.*Anton Arhipov
 
Con-FESS 2015 - Is your profiler speaking to you?
Con-FESS 2015 - Is your profiler speaking to you?Con-FESS 2015 - Is your profiler speaking to you?
Con-FESS 2015 - Is your profiler speaking to you?Anton Arhipov
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаAnton Arhipov
 
Загрузчики классов в Java - коллекция граблей
Загрузчики классов в Java - коллекция граблейЗагрузчики классов в Java - коллекция граблей
Загрузчики классов в Java - коллекция граблейAnton Arhipov
 
JavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistJavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistAnton Arhipov
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to GroovyAnton Arhipov
 
JPoint 2016 - Bytecode
JPoint 2016 - BytecodeJPoint 2016 - Bytecode
JPoint 2016 - BytecodeAnton Arhipov
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistAnton Arhipov
 
Joker 2016 - Bytecode 101
Joker 2016 - Bytecode 101Joker 2016 - Bytecode 101
Joker 2016 - Bytecode 101Anton Arhipov
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerAnton Arhipov
 
Devclub 01/2017 - (Не)адекватное Java-интервью
Devclub 01/2017 - (Не)адекватное Java-интервьюDevclub 01/2017 - (Не)адекватное Java-интервью
Devclub 01/2017 - (Не)адекватное Java-интервьюAnton Arhipov
 
Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsAnton Arhipov
 
Jenkins Evolutions - JEEConf 2012
Jenkins Evolutions - JEEConf 2012Jenkins Evolutions - JEEConf 2012
Jenkins Evolutions - JEEConf 2012Anton Arhipov
 
Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistAnton Arhipov
 
Criminal Record Management
Criminal Record ManagementCriminal Record Management
Criminal Record ManagementKhokan Sardar
 
Voxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistVoxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistAnton Arhipov
 
Crime Record Management System (CRMS)
Crime Record Management System (CRMS)Crime Record Management System (CRMS)
Crime Record Management System (CRMS)Zara Tariq
 

Viewers also liked (20)

Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Improve your Developer Experiece using the WAS Liberty Profile with JRebel Improve your Developer Experiece using the WAS Liberty Profile with JRebel
Improve your Developer Experiece using the WAS Liberty Profile with JRebel
 
import continuous.delivery.*
import continuous.delivery.*import continuous.delivery.*
import continuous.delivery.*
 
Taming Java Agents
Taming Java AgentsTaming Java Agents
Taming Java Agents
 
Con-FESS 2015 - Is your profiler speaking to you?
Con-FESS 2015 - Is your profiler speaking to you?Con-FESS 2015 - Is your profiler speaking to you?
Con-FESS 2015 - Is your profiler speaking to you?
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчика
 
Загрузчики классов в Java - коллекция граблей
Загрузчики классов в Java - коллекция граблейЗагрузчики классов в Java - коллекция граблей
Загрузчики классов в Java - коллекция граблей
 
JavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with JavassistJavaOne 2015 - Having fun with Javassist
JavaOne 2015 - Having fun with Javassist
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
JPoint 2016 - Bytecode
JPoint 2016 - BytecodeJPoint 2016 - Bytecode
JPoint 2016 - Bytecode
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With Javassist
 
Joker 2016 - Bytecode 101
Joker 2016 - Bytecode 101Joker 2016 - Bytecode 101
Joker 2016 - Bytecode 101
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
 
Devclub 01/2017 - (Не)адекватное Java-интервью
Devclub 01/2017 - (Не)адекватное Java-интервьюDevclub 01/2017 - (Не)адекватное Java-интервью
Devclub 01/2017 - (Не)адекватное Java-интервью
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Oredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java AgentsOredev 2015 - Taming Java Agents
Oredev 2015 - Taming Java Agents
 
Jenkins Evolutions - JEEConf 2012
Jenkins Evolutions - JEEConf 2012Jenkins Evolutions - JEEConf 2012
Jenkins Evolutions - JEEConf 2012
 
Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with Javassist
 
Criminal Record Management
Criminal Record ManagementCriminal Record Management
Criminal Record Management
 
Voxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistVoxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with Javassist
 
Crime Record Management System (CRMS)
Crime Record Management System (CRMS)Crime Record Management System (CRMS)
Crime Record Management System (CRMS)
 

Similar to NetBeans Plugin Development: JRebel Experience Report

比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for JoomlaLuke Summerfield
 
COScheduler In Depth
COScheduler In DepthCOScheduler In Depth
COScheduler In DepthWO Community
 
From android/ java to swift (2)
From android/ java to swift (2)From android/ java to swift (2)
From android/ java to swift (2)allanh0526
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptGuy Royse
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationBartosz Konieczny
 
An Introduction to AngularJs Unittesting
An Introduction to AngularJs UnittestingAn Introduction to AngularJs Unittesting
An Introduction to AngularJs UnittestingInthra onsap
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196Mahmoud Samir Fayed
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31Mahmoud Samir Fayed
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, PloneQuintagroup
 
Slaven tomac unit testing in angular js
Slaven tomac   unit testing in angular jsSlaven tomac   unit testing in angular js
Slaven tomac unit testing in angular jsSlaven Tomac
 
Java agents are watching your ByteCode
Java agents are watching your ByteCodeJava agents are watching your ByteCode
Java agents are watching your ByteCodeRoman Tsypuk
 
Android Automated Testing
Android Automated TestingAndroid Automated Testing
Android Automated Testingroisagiv
 
Do you really get class loaders?
Do you really get class loaders? Do you really get class loaders?
Do you really get class loaders? guestd56374
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3Simon Su
 

Similar to NetBeans Plugin Development: JRebel Experience Report (20)

比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for Joomla
 
COScheduler In Depth
COScheduler In DepthCOScheduler In Depth
COScheduler In Depth
 
From android/ java to swift (2)
From android/ java to swift (2)From android/ java to swift (2)
From android/ java to swift (2)
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customization
 
An Introduction to AngularJs Unittesting
An Introduction to AngularJs UnittestingAn Introduction to AngularJs Unittesting
An Introduction to AngularJs Unittesting
 
Spring data requery
Spring data requerySpring data requery
Spring data requery
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, Plone
 
Slaven tomac unit testing in angular js
Slaven tomac   unit testing in angular jsSlaven tomac   unit testing in angular js
Slaven tomac unit testing in angular js
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
Ocl 09
Ocl 09Ocl 09
Ocl 09
 
Java agents are watching your ByteCode
Java agents are watching your ByteCodeJava agents are watching your ByteCode
Java agents are watching your ByteCode
 
Android Automated Testing
Android Automated TestingAndroid Automated Testing
Android Automated Testing
 
Do you really get class loaders?
Do you really get class loaders? Do you really get class loaders?
Do you really get class loaders?
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 

More from Anton Arhipov

JavaZone 2022 - Building Kotlin DSL.pdf
JavaZone 2022 - Building Kotlin DSL.pdfJavaZone 2022 - Building Kotlin DSL.pdf
JavaZone 2022 - Building Kotlin DSL.pdfAnton Arhipov
 
TechTrain 2019 - (Не)адекватное техническое интервью
TechTrain 2019 - (Не)адекватное техническое интервьюTechTrain 2019 - (Не)адекватное техническое интервью
TechTrain 2019 - (Не)адекватное техническое интервьюAnton Arhipov
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCityAnton Arhipov
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCityAnton Arhipov
 
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
Devoxx Ukraine 2018 - Kotlin DSL in under an hourDevoxx Ukraine 2018 - Kotlin DSL in under an hour
Devoxx Ukraine 2018 - Kotlin DSL in under an hourAnton Arhipov
 
GeeCON Prague 2018 - Kotlin DSL in under an hour
GeeCON Prague 2018 - Kotlin DSL in under an hourGeeCON Prague 2018 - Kotlin DSL in under an hour
GeeCON Prague 2018 - Kotlin DSL in under an hourAnton Arhipov
 
Build pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSLBuild pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSLAnton Arhipov
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCityAnton Arhipov
 
JavaDay Kiev 2017 - Integration testing with TestContainers
JavaDay Kiev 2017 - Integration testing with TestContainersJavaDay Kiev 2017 - Integration testing with TestContainers
JavaDay Kiev 2017 - Integration testing with TestContainersAnton Arhipov
 
GeeCON Prague 2017 - TestContainers
GeeCON Prague 2017 - TestContainersGeeCON Prague 2017 - TestContainers
GeeCON Prague 2017 - TestContainersAnton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleJavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleAnton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingJavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationJUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationAnton Arhipov
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleAnton Arhipov
 
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
JEEConf 2017 - The hitchhiker’s guide to Java class reloadingJEEConf 2017 - The hitchhiker’s guide to Java class reloading
JEEConf 2017 - The hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with JavassistJEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with JavassistAnton Arhipov
 
Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 

More from Anton Arhipov (20)

JavaZone 2022 - Building Kotlin DSL.pdf
JavaZone 2022 - Building Kotlin DSL.pdfJavaZone 2022 - Building Kotlin DSL.pdf
JavaZone 2022 - Building Kotlin DSL.pdf
 
Idiomatic kotlin
Idiomatic kotlinIdiomatic kotlin
Idiomatic kotlin
 
TechTrain 2019 - (Не)адекватное техническое интервью
TechTrain 2019 - (Не)адекватное техническое интервьюTechTrain 2019 - (Не)адекватное техническое интервью
TechTrain 2019 - (Не)адекватное техническое интервью
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCity
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCity
 
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
Devoxx Ukraine 2018 - Kotlin DSL in under an hourDevoxx Ukraine 2018 - Kotlin DSL in under an hour
Devoxx Ukraine 2018 - Kotlin DSL in under an hour
 
GeeCON Prague 2018 - Kotlin DSL in under an hour
GeeCON Prague 2018 - Kotlin DSL in under an hourGeeCON Prague 2018 - Kotlin DSL in under an hour
GeeCON Prague 2018 - Kotlin DSL in under an hour
 
Build pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSLBuild pipelines with TeamCity and Kotlin DSL
Build pipelines with TeamCity and Kotlin DSL
 
Build pipelines with TeamCity
Build pipelines with TeamCityBuild pipelines with TeamCity
Build pipelines with TeamCity
 
JavaDay Kiev 2017 - Integration testing with TestContainers
JavaDay Kiev 2017 - Integration testing with TestContainersJavaDay Kiev 2017 - Integration testing with TestContainers
JavaDay Kiev 2017 - Integration testing with TestContainers
 
GeeCON Prague 2017 - TestContainers
GeeCON Prague 2017 - TestContainersGeeCON Prague 2017 - TestContainers
GeeCON Prague 2017 - TestContainers
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
 
JavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleJavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassle
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
 
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingJavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
 
JUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationJUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentation
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
JEEConf 2017 - The hitchhiker’s guide to Java class reloadingJEEConf 2017 - The hitchhiker’s guide to Java class reloading
JEEConf 2017 - The hitchhiker’s guide to Java class reloading
 
JEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with JavassistJEEConf 2017 - Having fun with Javassist
JEEConf 2017 - Having fun with Javassist
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 

Recently uploaded

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 

Recently uploaded (20)

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 

NetBeans Plugin Development: JRebel Experience Report

  • 1. NetBeans Plugin Development: JRebel Experience Report JavaOne SF 2012
  • 2.
  • 3. whoami Anton Arhipov JRebel Product Lead @antonarhipov anton@zeroturnaround.com
  • 4. Agenda • JRebel intro – Plugin requirements • NetBeans plugin development • Integrating with NetBeans server adaptors • Integrating with NetBeans debugger • Packaging & publishing
  • 6. The Turnaround Cycle Make changes AVG 2.5 min Build, Observe deploy, results wait
  • 7. Make changes in IDE ClassLoader Framework MyObject.class Code 101000101 New code JRebel 100010010 111000100 101010010 MyObject Configuration (XML, annotations,..)
  • 9. Why IDE plugin? Usability Automation Debugger
  • 10. JRebel Plugin for NetBeans Workbench Settings, UX JRebel Plugin NetBeans Process VM args Launcher Breakpoints Debugger Stepping
  • 12. Books
  • 13. UI Elements • Buttons/Actions • Toolbars/Menus • Settings/Options • Popups • etc
  • 14. layers.xml <folder name="Actions"> <folder name="JRebel"> <file name="JRebelToggleAction.instance"> <attr name="delegate" newvalue="o.z.j.n.JRebelToggleAction"/> </file> </folder> </folder> <folder name="Toolbars"> <folder name="Build"> <file name="JRebelToggleAction.shadow"> <attr name="originalFile" stringvalue="Actions/JRebel/JRebelToggleAction.instance"/> <attr name="position" intvalue="250"/>
  • 16. Options (Old API) <folder name="OptionsDialog"> <file name="JRebelOptions.instance"> <attr name="instanceCreate" methodvalue="o.n.s.o.OptionsCategory.createCategory"/> <attr name="controller" newvalue="o.z.j.n.JRebelOptionsPanelController"/> </file> </folder> <folder name="Services"> <file name="org-zeroturnaround-jrebel-netbeans-options.settings" url="options.xml"/> </folder>
  • 17. Options (New API) @OptionsPanelController.SubRegistration( location = "Advanced", displayName = "#AdvancedOption_DisplayName_Super", keywords = "#AdvancedOption_Keywords_Super", keywordsCategory = "Advanced/Super") @org.openide.util.NbBundle.Messages( {"AdvancedOption_DisplayName_Super=Super", "AdvancedOption_Keywords_Super=super"}) public final class SuperOptionsPanelController extends OptionsPanelController {
  • 19. JVM arguments • JRebel is bootstrapped using JVM arguments: -javaagent:/path/to/jrebel.jar -noverify -Xbootclasspath/p:jrebel-bootstrap.jar;jrebel.jar -Drebel.log=true -Drebel.jersey_plugin=true • Various NetBeans project types pass JVM arguments slightly differently: Web project VS Maven project JBoss VS Tomcat VS Glassfish
  • 20. Server settings: Tomcat Can put your arguments here
  • 21. Server settings: Glassfish No VM arguments?
  • 23. Toggle Simplest, from the user’s point of view: should not care about project type of runtime differences
  • 24. Toggle public final class JRebelToggleAction extends BooleanStateAction { public void initialize() { super.initialize(); setBooleanState(JRebelSettings.isEnabled()); } public void actionPerformed(ActionEvent ev) { super.actionPerformed(ev); JRebelSettings.setEnabled(getBooleanState()); // NbPreferences.forModule(JRebelSettings.class) // .putBoolean(“enabled”, true); } }
  • 25. Challenge No extension points provided by the NetBeans platform Load-Time Weaving of NetBeans platform classes Might not be the brightest bulb idea, but seems to work fine 
  • 27. org.openide.modules.ModuleInstall public class Installer extends ModuleInstall { @Override public void restored() { // patch platform classes here } }
  • 28. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() .lookup(ClassLoader.class); Object o = ClassLoader#findLoadedClass(classToPatch ) ClassPool cp = new ClassPool(); cp.appendClassPath(new LoaderClassPath(cl)); CtClass ctc = cp.get(classToPatch); patch(cp, ctc); ctc.toClass(cl, null);
  • 29. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() .lookup(ClassLoader.class); e.g. Object o = ClassLoader#findLoadedClass(classToPatch ) “org.netbeans.modules.glassfish.common.StartTask” “org.netbeans.modules.tomcat5.ide.StartTomcat$StartRunnable” ClassPool cp = new ClassPool(); etc cp.appendClassPath(new LoaderClassPath(cl)); CtClass ctc = cp.get(classToPatch); patch(cp, ctc); ctc.toClass(cl, null);
  • 30. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() .lookup(ClassLoader.class); Object o = ClassLoader#findLoadedClass(classToPatch ) a class loader capable for finding ClassPool cp = new ClassPool(); module resources from any cp.appendClassPath(new LoaderClassPath(cl)); CtClass ctc = cp.get(classToPatch); patch(cp, ctc); ctc.toClass(cl, null);
  • 31. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() .lookup(ClassLoader.class); Object o = ClassLoader#findLoadedClass(classToPatch ) ClassPool= ClassLoader.class Method m cp = new ClassPool(); cp.appendClassPath(new LoaderClassPath(cl)); .getDeclaredMethod("findLoadedClass", String.class); CtClass ctc = cp.get(classToPatch); m.setAccessible(true); patch(cp, ctc); Object o = m.invoke(cl, patchedClassName); ctc.toClass(cl, null);
  • 32. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() Enter Javassist .lookup(ClassLoader.class); Object o = ClassLoader#findLoadedClass(classToPatch ) ClassPool cp = new ClassPool(); cp.appendClassPath(new LoaderClassPath(cl)); CtClass ctc = cp.get(classToPatch); patch(cp, ctc); ctc.toClass(cl, null);
  • 33. Patcher String classToPatch = … ClassLoader cl = Lookup.getDefault() .lookup(ClassLoader.class); Object o = ClassLoader#findLoadedClass(classToPatch ) ClassPool cp = new ClassPool(); cp.appendClassPath(new LoaderClassPath(cl)); CtClass ctc = cp.get(classToPatch); This is where patching patch(cp, ctc); happens really ctc.toClass(cl, null);
  • 34. patch(…) final CtMethod method = ctc.getDeclaredMethod("run"); method.instrument(new ExprEditor() { public void edit(MethodCall m) { if ("getJavaOpts".equals(m.getMethodName())) { m.replace( "if (command == CommandType.START)" + OPTS + "$_ = opts + $proceed($$);"); } } });
  • 35. patch(…) final CtMethod method = ctc.getDeclaredMethod("run"); method.instrument(new ExprEditor() { public void edit(MethodCall m) { Patching if ("getJavaOpts".equals(m.getMethodName())) { StartTomcat$StartRunnable#run() m.replace( for Tomcat launcher "if (command == CommandType.START)" + OPTS + "$_ = opts + $proceed($$);"); } } });
  • 36. patch(…) final CtMethod method = ctc.getDeclaredMethod("run"); method.instrument(new ExprEditor() { public void edit(MethodCall m) { if ("getJavaOpts".equals(m.getMethodName())) { m.replace( "if (command == CommandType.START)" + OPTS + "$_ =Should+append custom options opts $proceed($$);"); } to getJavaOpts result } });
  • 37. patch(…) final CtMethod method = ctc.getDeclaredMethod("run"); String OPTS = "ClassLoader cl = (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class);" + method.instrument(new ExprEditor() { "Class locator = cl.loadClass("org.zeroturnaround.jrebel.netbeans.JRebelLocator");" + public void edit(MethodCall m) { "Method getJRebelOptsStr = locator.getMethod("getJRebelOptsStr", null);" + if ("getJavaOpts".equals(m.getMethodName())) { "String opts = (String) getJRebelOptsStr.invoke(null, null);"; m.replace( "if (command == CommandType.START)" + OPTS + "$_ = opts + $proceed($$);"); } } });
  • 38. patch(…) final CtMethod method = ctc.getDeclaredMethod("run"); String OPTS = "ClassLoader cl = (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class);" + method.instrument(new ExprEditor() { "Class locator = cl.loadClass("org.zeroturnaround.jrebel.netbeans.JRebelLocator");" + public void edit(MethodCall m) { "Method getJRebelOptsStr = locator.getMethod("getJRebelOptsStr", null);" + if ("getJavaOpts".equals(m.getMethodName())) { "String opts = (String) getJRebelOptsStr.invoke(null, null);"; m.replace( "if (command == CommandType.START)" + OPTS + "$_ = opts + $proceed($$);"); } -javaagent:/path/to/jrebel.jar etc } });
  • 39. Pros & Cons + Can get stuff done even if the platform doesn’t provide a proper interface - Brittle for maintenance
  • 40. New API (7.2) • SPI for JVM options passed to SE program or EE server (Bug 206196) @StartupArgumentsProvider.Registration( position=10, displayName="#DESC_JRebel", startMode={StartMode.NORMAL, StartMode.DEBUG}) public class MyArgsProvider implements StartupArgumentsProvider { @Override public List<String> getArguments(ServerInstance instance, StartMode mode)
  • 41. Dude, where’s my car breakpoint? DEBUGGER INTEGRATION
  • 43. Breakpoints Line 14: same breakpoint, but new version of the class Need to “transfer” the breakpoint from original class to versioned class
  • 45. New API (7.3) • Allow to provide additional binary classes to submit breakpoints on (Bug 215680) @BreakpointClassFilter.Registration public class MyFilter extends BreakpointClassFilter { @Override public ClassNames filterClassNames(ClassNames classNames, JPDABreakpoint breakpoint){} }
  • 48. Packaging Plugin has to be signed Module descriptor JRebel distribution Dependencies Plugin itself
  • 49. Maven Build • NetBeans modules maven plugin – nbm-maven-plugin • Properties maven plugin – properties-maven-plugin • Maven dependency plugin – maven-dependency-plugin • Maven compiler plugin • Maven JAR plugin
  • 50. Publishing • http://plugins.netbeans.org/ • Verification is performed manually (by volunteers) • Main criteria: should not break the platform • Takes some time
  • 51. Lessons Learned • UX is hard • Follow the logic of the target IDE • Follow the new APIs • Annotations over layer.xml • If no required extension point provided, can get around with patching via ModuleInstall • Publishing is not 100% predictable process
  • 52. Credits • Big thanks to NetBeans team for awesome co- operation & providing the new API for debugger and server adaptors!

Editor's Notes

  1. List the requirements for the plugin