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

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
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
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 

Recently uploaded (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
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...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 

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