I'm just transitioning from Ruby to Java and debugging in Ruby was made much easier via the 'Pry' gem. You could place binding.pry anywhere in the code and upon running the app, the code would stop or 'freeze' at the binding.pry and allow you to manipulate variables, create new objects, return values, etc - essentially it dropped you into a playground environment at that given point in time.
Anything similar in Java?
Debugging is the way to go, if you are used to run IRB/pry/rails console in production then you need to get in the habit of changing your connection settings to production which is very dangerous but an option for a language that does not offer a REPL (read eval print loop) console.
Setup a Java class just to be the entry point of the code you want to debug then add the breakpoints and run it in Debug mode. Every time you need to debug something else, change that entry point class to do something else.
You may as well just use breakpoints in your routes/endpoints, you add a breakpoint to a route and you trigger an API call either with curl, postman or any HTTP client that triggers that route.
Related
Sometimes you need just to check how are some values in your application changing in time. Usually, you can use the log, but imagine that your application is on severs already and make the whole CI/CD cycle, just to add a few temporary log statements is overkill. Or variables are in 3-rd party libraries, and you don't want to patch it.
Of course, you can (remotely) debug your application, but it may be an issue to suspend the thread and check several variables again and again and again.
Such functionality is available in the JetBrains IntelliJ IDEA out of the box - tracepoint, but what about Eclipse?
Fortunately, you can implement the "virtual logging" with Eclipse.
To do it:
Start the debug session
add the conditional breakpoint to the line that you want to add a log statement
Write the log statement to the breakpoint condition and return false;
That's all. The application will not suspend while passing breakpoint but will write to output the value of the variable
I have some Pax Exam tests. To execute the test normally, I just run the JUnit class in Eclipse. If I want to step through the code in the Eclipse debugger, I have to make it set the debug options, including the flag to make it wait for the debugger connection, which is a separate process I have to run. I'm presently having this code check for a "debug" system property to enable this, but that's sort of annoying.
It would be really nice if the #Configuration method can look at a system property or some other condition that will always be true if the code is executing in the debugger, so I could use that as a trigger to enable those flags, instead of a manually set "debug" system property.
I've already tried setting a breakpoint at the top of this method and inspecting all the system properties for something that might be set while in the debugger, but I didn't see anything.
Update:
Just to be clear, I need to point out some details about how Pax Exam tests work, to better explain why I'm looking for a way to improve this process. When the test runs, it forks a Karaf container to run the test in. In order to run a test in the debugger, you have to force the code that runs in the container to set the "suspend=y" flag, which will wait for a debugger connection. You definitely don't want to do that if you're not debugging.
After starting the pax exam test running, you then have to run another debug configuration, to make a remote connection to the karaf container. Technically, the run configuration for the unit test itself doesn't need to be a debug configuration.
So, the easiest way to make this happen is to have the the code that initiates the container check for a "debug" system property (or whatever you want to call it), and when that is set, to set the debugger port and the "suspend=y" flag. If the property is not set, it doesn't do that.
So, if you're running the test without debug, you have to make sure that system property is not set. If you're debugging, you have to make sure it's set. It's an annoyance to have to edit the run configuration each time you need to go back and forth.
So, what I was intending was to start the unit test run configuration as a debug configuration (even though it doesn't need to be), and for the code that starts the karaf container to detect that it's being run as a debug configuration, and set the "suspend=y" flag in that case.
I've concluded that there is no way for the code itself to detect this, but I'll detail in my own answer how I get the debugger to help me a bit.
I'm going to self-answer to address my original problem, although it isn't quite the answer to my original question, which the first answer does attempt to address. That answer doesn't help me, however.
My real need was to able to run my Pax Exam test so that when I first run the unit test, which is running the "server" portion of the Pax Exam test, it will know to provide the correct "-Xdebug" parameters to the server if I'm going to be using the debugger, and NOT to if I'm not using the debugger. I have code that checks for the "debug" system property and uses that to set the correct "-Xdebug" parameters, but I don't want to have to manually add or remove that parameter from the run configuration if I need to change how I'm running the test (going between debugging and not debugging).
So, as far as I can see, the best I can do is make it so that when I run the "server" portion of the unit test in the debugger (which otherwise doesn't actually have to be in the debugger, as it's only the client side that needs it), this will cause the system property I'm checking for to be set, so it will set the correct flags.
I'm not aware of any feature in Eclipse that lets me run particular predefined snippets of code when I start any debugging session (I mean "any", not a "particular" debugging session), but there is something that comes close, even though it's a bit of a hack.
What I did was set a breakpoint at the top of the method that sets the karaf configuration to be started, and I made the breakpoint conditional, with the following expression:
(System.setProperty("debug", "true") != null) && false
This will set the system property I need, but then not stop, as the final expression will be false.
Technically, it doesn't even need to be in this method, it just has to be hit before the karaf options are set.
This stays as a workspace setting, so I don't need to re-add this every time I start Eclipse.
Update:
With the upgrade to Oxygen, this can be slightly simpler, with the new "tracepoints" feature (https://www.eclipse.org/eclipse/news/4.7/jdt.php#toggle-trace-point). Just "toggle tracepoint" and set the expression to 'System.setProperty("debug", "true")'
If you are debugging eclipse application there is a way, you can use Platform.isDebug() to check whether your application is using debug or run lanuch configuration.
In your case i.e checking in Junit test run, I am not aware of how to detect whether we are using run/debug launch config. But strongly believe that there must a way to find it out with code like what you suggested using System Class.
Why can't you pass your own argument/environment variable in Junit debug launch config(With -D= in Arguments tab or in Environment tab? and use it in the test code to detect?
I'm one of those guys who step through their code a lot during development. Beginning with version 1.6.4 of the GAE Java development server, the server has been instrumented with calls to a function named Runtime.checkRestricted. This causes two inconveniences when I step through my code:
Whenever I step into a function, the debugger goes into the function Runtime.checkRestricted (for which there is no source code) at least once, often multiple times.
Whenever I step over a function call which has a large call tree underneath, it takes a very long time for the debugger to come back. (That's always a problem in the Eclipse Java debugger, but now it's really bad.)
For me, all this causes a serious drain on productivity. Is there any way to disable this instrumentation, or at least to prevent the debugger from stepping into it? I am using Eclipse with the GAE plugin.
Add a step filter to filter out all step breakpoints you are not interested in. The Eclipse documention provides a guide how to set up step filter.
In your specific case, you will want to add a package filter for com.google.appengine.tools.development.* , as this package and its subpackages contain GAE's Runtime class and RuntimeHelper class. Finally, don't forget to activate the option "Use Step Filters" (Shift + F5).
I'm working with a legacy Java app that is new to me so one way to figure out how it works and find things easier, I have thought would be to be able to get the full stack trace after I perform actions, so as to be able to see which classes are being used based on a particular UI action. I had thought this was possible in the debugger but it seems that it only works if I insert a breakpoint and in this case part of the purpose of this is so that I don't have to know what's being called to be able to insert the breakpoint first (as this would help tell me that).
I apologize if this is a basic question, I have searched on this but I'm not finding the correct answer.
This doesn't directly answer your question, but maybe it will solve your problem better. Take a look at BTrace. It lets you instrument a running Java app and insert some basic code of your own. You could, for instance, have it write out entire method call chains to help you find your way through the app. It's somewhat similar to AspectJ, but with an entirely different purpose and requiring no change in the project source:
"BTrace is a safe, dynamic tracing tool for Java. BTrace works by dynamically (bytecode) instrumenting classes of a running Java program. BTrace inserts tracing actions into the classes of a running Java program and hotswaps the traced program classes."
A few suggestions:
Some profilers will allow you to walk from any particular method up (and sometimes down) to see what's calling and being called. I've found this surprising informative about flow, even in apps I thought I knew well.
For understanding the mainline flow, I don't think there's a better substitute for working interactively with a debugger. It will lead you into learning other important things. Not what you wanted to hear, I know. This presumes that you can rapidly restart the app when you miss a key off-ramp.
Reverse-designing large legacy apps is the one place where I use UML fairly regularly. There's too much to keep in my head to form a good big picture. If you have a UML tool that will do reverse-engineering, load it up with the app, then probably prune down hard on the classes you don't care about, because they are trivial or obvious. Arrange the diagrams in a way that helps you understand. I've used Together, Magic Draw, and Visual Paradigm in this way. Together worked the best - but it was a decade ago.
When you are in the debugger perspective, you will see a view showing the launched processes. In that view you can tell it to pause all threads of a process. Once stopped, you will be able to browse through threads to see what they are all doing. To try to catch what a particular action is doing, you would have to start the action and then quickly pause all threads.
You could always run the application with the VM arg of -verbose:class. You could then watch the console output and see what classes the VM is loading when you perform a particular action. This could possibly give you a starting place for where to place breakpoints. This won't always work depending on the scenario, but may be helpful.
Another trick you can use is to figure what classes you know that have to be involved in the code path you are trying to trap. For instance, you mentioned that it's a Java EE web app and therefore the action is likely some kind of a servlet interaction (at some level). I don't have the API in front of me, but you can place a breakpoint on the method in the response object where the output stream is retrieved. Once that breaks, you will know the code that's trying to service the request.
You can always see where a method is called by clicking "Open Call Hierarchy" from eclipse (left click on the selected method or CTRL+ALT+H ). Also, you always can inspect where a method/class is defined by clicking "Open Declaration" (left click on the selected method/class or F3).
Is it possible to debug a Rails application in a similar way to a Java application - setting breakpoints and stepping into the code?
What are the best tools for this?
I have a hybrid Java/Ruby on Rails application which I can run in Eclipse or Netbeans.
I would like to step into some code in this app and try to figure out the cause of a problem I'm having.
In Eclipse if I set a breakpoint in my blog_controller and then choose the 'Debug' button, it seems to use the ruby-debug-ide gem to execute the code but I get this unhelpful output and no option to step into any source:
Fast Debugger (ruby-debug-ide 0.4.5) listens on localhost:56726
./war/WEB-INF/app/controllers/blog_controller.rb:1
C:/Ruby18/lib/ruby/gems/1.8/gems/ruby-debug-ide-0.4.5/lib/ruby-debug.rb:101:in `debug_load'
C:/Ruby18/lib/ruby/gems/1.8/gems/ruby-debug-ide-0.4.5/lib/ruby-debug.rb:101:in `debug_program'
C:/Ruby18/lib/ruby/gems/1.8/gems/ruby-debug-ide-0.4.5/bin/rdebug-ide:82
C:/Ruby18/bin/rdebug-ide:19:in `load'
C:/Ruby18/bin/rdebug-ide:19
Uncaught exception: uninitialized constant ApplicationController
I'm not sure if I'm doing something wrong or if this is all I can expect.
The debugger I use the most is the ruby-debug gem, which is a gdb-esque command line debugger. Once you learn a few commands it is very quick and effective, and provides you with some handy features like being able to fire up irb in the context of your program and make on-the-fly changes.
And being command line based it comes in handy when you need to debug a on a remote server.
You can expect more. I have used Aptana's RadRails version of Eclipse to debug a Rails app as you describe--setting breakpoints and stepping through the code.
You may be doing something wrong. It looks as if it is trying to debug an individual controller file, rather than debugging the Rails app. When I try to execute a controller file from the command line, I get a similar message:
C:\workspace\myapp\app\controllers>ruby users_controller.rb
users_controller.rb:1: uninitialized constant ApplicationController (NameError)
In Aptana RadRails, I choose Run > Debug As > Ruby Application to debug the app.
For the vim users I strongly recomend looking into the vim-ruby-debugger, which fits in great with Tim Pope's rails.vim scripts.
It gives you a handy :Rdebugger command, allows you to set breakpoints and open a split window to display variable values.
maybe not relevant, but I wanted to post somewhere: got the error: "undefined method `run_init_script' for Debugger:Module" running the debugger in rails 2.3.2. Did a sudo gem install ruby-debug and the problem went away.
I'd recommend just setting up breakpoints (I actually just puts to console) for 99% of debugging with RoR - this method is simple and usable across any IDE, so you never need to learn how a new debugger works.
Actually, I had the same problem with Aptana. Run > Debug As > Ruby Application just doesn't work. I finally made the debugger work by going to the Servers tab, and then start the server in debug mode. After that, set some breakpoints and trigger the corresponding action. Hope this helps.
Debugging? That's just knowing where to look in the case of Ruby (and by extension, Rails) most of the time.
The problem in this case is that you probably still have your ApplicationController called application.rb where it should be renamed to application_controller.rb.
Debuggin in rails is simple if you know how to read the error stacktrace!! But if you need to explicitly watch out the values during the runtime then u can use the rails breakpointer.Below is the link to how-to on breakpointer ..hope this helps!!!
http://destiney.com/blog/rails-breakpointer
I can't speak for Eclipse (never worked well for me) or Aptana (not tried) but from experience I can say that both NetBeans and RubyMine will do what you want. I both cases you should probably make sure that the ruby-debug-base and ruby-debug-ide gems are up-to-date: RubyMine in particular didn't work for me until that was done.