SlideShare une entreprise Scribd logo
1  sur  52
Télécharger pour lire hors ligne
NetBeans Plugin Development:
  JRebel Experience Report
         JavaOne SF 2012
NetBeans Plugin Development: JRebel Experience Report
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!

Contenu connexe

Tendances

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
 

Tendances (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
 

En vedette

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
 

En vedette (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)
 

Similaire à 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
 

Similaire à 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
 

Plus de 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
 

Plus de 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
 

Dernier

COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 

Dernier (20)

COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 

NetBeans Plugin Development: JRebel Experience Report

  • 1. NetBeans Plugin Development: JRebel Experience Report JavaOne SF 2012
  • 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!

Notes de l'éditeur

  1. List the requirements for the plugin