Show last authors
1 There are several possibilities for debugging XWiki:
2
3 {{toc/}}
4
5 = Debug mode =
6
7 [Since 7.1]
8
9 It's possible to enable debug log by adding ##debug=true## (as in [[http://127.0.0.1:8080/xwiki/bin/Main/WebHome?debug=true]]) to the URL. This provide various details on what exactly happens during the request.
10
11 == Elapsed time tree ==
12
13 A detailed tree of how long has been spent in each step. You can add you own step to the tree by using [[progress API>>extensions:Extension.Job Module||anchor="HNotifyaboutprogress"]].
14
15 {{image reference="elapsedtimetree.png"/}}
16
17 = Debugging XWiki from your IDE =
18
19 == Debugging with Eclipse ==
20
21 Once you've gotten the debugger working, you'll wonder how you ever survived without it.
22
23 === Complete tutorial based on M2E and WTP ===
24
25 [[Debug XWiki with Eclipse>>DebugXEWithEclipse]]
26
27 === Debug a XWiki released version ===
28
29 * Follow the steps from [[Building In Eclipse>>BuildingInEclipse]] including the optional "Import the WAR as a web project".
30 * Select from the Eclipse menu **Run > Debug...**
31 * Create a new configuration for your server
32 * Hit the **Debug** button
33 * Set breakpoints, step through code, have fun!
34
35 WTP will deploy XWiki into ##{workspace_location}/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/webapps/xwiki##. If you suspect a change has not been deployed correctly (e.g. a change to a config file), check there to confirm.
36
37 If you are working on an XWiki plugin in a separate project in your workspace, you can ensure it is automatically deployed to XWiki's ##WEB-INF/lib## directory when debugging. Open the project properties of the XWiki project resulting from the WAR import above, go to the ##J2EE Module Dependencies## section, and add your plugin project.
38
39 === Using Firebug when debugging a selenium test ===
40
41 For that you will need to install Firebug [[as a global extension>>http://kb.mozillazine.org/Installing_extensions#Global_installation]]
42
43 = Remote Debugging =
44
45 To perform remote debugging, start your wiki in debug mode. To do this you can:
46
47 * use the ##start_xwiki_debug.sh## executable if you're using the Standalone packaging
48 * modify the way you start your container and ensure that the following JVM parameters are passed:(((
49 {{code}}
50 -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
51 {{/code}}
52
53 For example, for Jetty you could use the following start script:
54
55 {{code}}
56 #!/bin/sh
57
58 JETTY_HOME=.
59 JETTY_PORT=8080
60 JAVA_OPTS="-Xmx300m -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
61
62 java $JAVA_OPTS -Dfile.encoding=iso-8859-1 -Djetty.port=$JETTY_PORT -Djetty.home=$JETTY_HOME -jar $JETTY_HOME/start.jar
63 {{/code}}
64
65 If you are using the Tomcat service on Windows, you should modify the JVM args with the Tomcat Service Configuration Panel. Select the Java tab and add each of the options **on a separate line**. For example:
66
67 {{code}}
68 -Dcatalina.home=C:\Program Files\Apache Software Foundation\Tomcat 5.5
69 -Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 5.5
70 -Djava.endorsed.dirs=C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\endorsed
71 -Djava.io.tmpdir=C:\Program Files\Apache Software Foundation\Tomcat 5.5\temp
72 -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
73 -Djava.util.logging.config.file=C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\logging.properties
74 -Xdebug
75 -Xnoagent
76 -Djava.compiler=NONE
77 -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
78 {{/code}}
79 )))
80
81 Then, in your favorite IDE, open the XWiki project and run a remote debugging session, attached to the socket on port 5005. For example, if you're using IntelliJ IDEA, go to ##Run|Edit Configurations...## and create a new ##Remote## configuration (default parameters should be fine). Then execute it and IDEA will connect to the executing JVM.
82
83 You can then place breakpoints in your source code.
84
85 Debugging options for ##start_xwiki_debug.sh##:
86
87 * Use the ##~-~-suspend## parameter to tell the JVM to wait until someone connect to the debugging port before progressing.
88 * Use the ##JETTY_DEBUG_PORT## environment variable to control the JVM debug port to use (default is ##5005##).
89 * {{version since="12.8RC1"}}Use the ##-dp <number>## (or ##-~-debugPort <number>##) parameter to control the JVM debug port to use (default is ##5005##).{{/version}}
90
91 = Logging =
92
93 == Turning on logging inside XWiki ==
94
95 See the [[Logging page in the Admin guide>>platform:AdminGuide.Logging]].
96
97 == Logging shutdown operations ==
98
99 {{info}}XWiki 6.3M1+{{/info}} To log debug information of what happens when there are shutdown operations, simply set the log level to ##DEBUG## for the ##org.xwiki.shutdown## logger:
100
101 {{code language="xml"}}
102 <logger name="org.xwiki.shutdown" level="info"/>
103 {{/code}}
104
105 == Logging calls at the database level ==
106
107 You have several options:
108
109 * Configure Hibernate to log SQL calls. To do this edit XWiki's log configuration file (see the [[Logging page>>platform:AdminGuide.Logging]]) and change the log level from ##warn## to ##trace## for the following:(((
110 {{code language="none"}}
111 <!-- Log HQL query parser activity -->
112 <logger name="org.hibernate.hql.ast.AST" level="warn"/>
113 <!-- Log just the SQL -->
114 <logger name="org.hibernate.SQL" level="warn"/>
115 <!-- Log JDBC bind parameters -->
116 <logger name="org.hibernate.type" level="warn"/>
117 <!-- Log schema export/update -->
118 <logger name="org.hibernate.tool.hbm2ddl" level="warn"/>
119 <!-- Log HQL parse trees -->
120 <logger name="org.hibernate.hql" level="warn"/>
121 <!-- Log cache activity -->
122 <logger name="org.hibernate.cache" level="warn"/>
123 <!-- Log transaction activity -->
124 <logger name="org.hibernate.transaction" level="warn"/>
125 <!-- Log JDBC resource acquisition -->
126 <logger name="org.hibernate.jdbc" level="warn"/>
127 <!-- Enable the following line if you want to track down connection leakages when using
128 DriverManagerConnectionProvider -->
129 <logger name="org.hibernate.connection.DriverManagerConnectionProvider" level="warn"/>
130 <!-- Log prepared statement cache activity -->
131 <logger name="org.hibernate.ps.PreparedStatementCache" level="warn"/>
132 {{/code}}
133 )))
134 * Use a wrapping JDBC driver such as [[log4jdbc>>http://code.google.com/p/log4jdbc/]] or [[p6spy>>http://sourceforge.net/projects/p6spy/]].
135 * (((
136 Turn on logging in your database. The configuration is database-dependent*
137
138 (((
139 For **HSQLDB**. Two solutions:* Solution 1: Edit ##WEB-INF/hibernate.cfg.xml## and modify the URL connection property to add ##hsqldb.sqllog=3##, as in:
140
141 (((
142 {{code language="none"}}
143 <property name="connection.url">jdbc:hsqldb:file:${environment.permanentDirectory}/database/xwiki_db;shutdown=true;hsqldb.sqllog=3</property>
144 {{/code}}
145 )))
146
147 * Solution 2: Using Byteman (See the section below for more information). For example the following rule (tested on HSQLDB 2.3.1) will log SQL statements with parameters and schema when there's more than 1 parameter:(((
148 {{code language="none"}}
149 RULE Log SQL Statement
150 CLASS org.hsqldb.Session
151 METHOD executeCompiledStatement(org.hsqldb.Statement, Object[], int)
152 AT ENTRY
153 IF $2.length > 0
154 DO traceln("SQL Statement = [" + $1.getSQL() + "], parameter 1 = [" + $2[0] + "], schema = [" + $1.getSchemaName().name + "]")
155 ENDRULE
156 {{/code}}
157
158 Will give for example:
159
160 {{code language="none"}}
161 SQL Statement = [select xwikidocum0_.XWD_ID as XWD1_0_0_, xwikidocum0_.XWD_FULLNAME as XWD2_0_0_, xwikidocum0_.XWD_NAME as XWD3_0_0_, xwikidocum0_.XWD_TITLE as XWD4_0_0_, xwikidocum0_.XWD_LANGUAGE as XWD5_0_0_, xwikidocum0_.XWD_DEFAULT_LANGUAGE as XWD6_0_0_, xwikidocum0_.XWD_TRANSLATION as XWD7_0_0_, xwikidocum0_.XWD_DATE as XWD8_0_0_, xwikidocum0_.XWD_CONTENT_UPDATE_DATE as XWD9_0_0_, xwikidocum0_.XWD_CREATION_DATE as XWD10_0_0_, xwikidocum0_.XWD_AUTHOR as XWD11_0_0_, xwikidocum0_.XWD_CONTENT_AUTHOR as XWD12_0_0_, xwikidocum0_.XWD_CREATOR as XWD13_0_0_, xwikidocum0_.XWD_WEB as XWD14_0_0_, xwikidocum0_.XWD_CONTENT as XWD15_0_0_, xwikidocum0_.XWD_VERSION as XWD16_0_0_, xwikidocum0_.XWD_CUSTOM_CLASS as XWD17_0_0_, xwikidocum0_.XWD_PARENT as XWD18_0_0_, xwikidocum0_.XWD_CLASS_XML as XWD19_0_0_, xwikidocum0_.XWD_ELEMENTS as XWD20_0_0_, xwikidocum0_.XWD_DEFAULT_TEMPLATE as XWD21_0_0_, xwikidocum0_.XWD_VALIDATION_SCRIPT as XWD22_0_0_, xwikidocum0_.XWD_COMMENT as XWD23_0_0_, xwikidocum0_.XWD_MINOREDIT as XWD24_0_0_, xwikidocum0_.XWD_SYNTAX_ID as XWD25_0_0_, xwikidocum0_.XWD_HIDDEN as XWD26_0_0_ from xwikidoc xwikidocum0_ where xwikidocum0_.XWD_ID=?], parameter 1 = [-4526159677276379501], schema = [TEST91]
162 {{/code}}
163 )))
164 )))
165 )))
166
167 == Logging HTTP calls ==
168
169 XWiki uses [[HTTP Client>>https://hc.apache.org/httpcomponents-client-ga/]] in most places and logging what it does is easy. You'll need to add the following to XWiki's ##logback.xml## file:
170
171 {{code language="xml"}}
172 <logger name="org.apache.http" level="debug"/>
173 <logger name="org.apache.http.headers" level="debug"/>
174 <logger name="org.apache.http.wire" level="debug"/>
175 {{/code}}
176
177 == Using Byteman ==
178
179 [[Byteman>>https://www.jboss.org/byteman]] is a great framework that allows to modify bytecode in a running JVM. It can easily be used to add logging (for ex) to find out what's happening in a running XWiki instance. Here's a quick tutorial:
180
181 * Download Byteman and unzip it in a directory. Set the ##$BYTEMAN_HOME## environment property to point to the directory where you've unzipped it. For example:
182 {{code}}export BYTEMAN_HOME=/Users/vmassol/dev/byteman/byteman-download-2.1.0{{/code}}
183 * Start an XWiki instance somewhere on the same machine
184 * Go to ##$BYTEMAN_HOME/bin## and connect Byteman to XWiki. For example:
185 {{code}}sh bminstall.sh -b -Dorg.jboss.byteman.transform.all jetty/start.jar{{/code}}
186 * Now create a Byteman rule by creating a file, for example ##my.btm## with the following:(((
187 {{code}}
188 RULE XWiki Docs loaded
189 CLASS XWikiHibernateStore
190 METHOD loadXWikiDoc
191 AT ENTRY
192 IF TRUE
193 DO traceln("Load document = " + $1.getDocumentReference())
194 ENDRULE
195 {{/code}}
196 )))
197 * Load this rule with: {{code}}sh bmsubmit.sh -l my.btm{{/code}}
198 * Call a URL in your wiki and check that the console prints the document references that get loaded! For example:(((
199 {{code}}
200 Load document = xwiki:Main.WebPreferences
201 Load document = xwiki:ColorThemes.DefaultColorTheme
202 Load document = xwiki:XWiki.SearchSuggestConfig
203 Load document = xwiki:XWiki.SearchSuggestConfig
204 Load document = xwiki:Dashboard.WebHome
205 Load document = xwiki:XWiki.GadgetClass
206 Load document = xwiki:Dashboard.WebHome
207 Load document = xwiki:Dashboard.WebPreferences
208 Load document = xwiki:Dashboard.colibri
209 Load document = xwiki:Main.Welcome
210 ...
211 {{/code}}
212 )))
213 * Modify your rule or add new rules to the same file and apply the changes with {{code}}sh bmsubmit.sh -l my.btm{{/code}}
214 * Remove your rules with {{code}}sh bmsubmit.sh -u{{/code}}
215
216 For more read [[A Byteman tutorial>>https://community.jboss.org/wiki/ABytemanTutorial]] or the [[Reference documentation>>http://downloads.jboss.org/byteman/2.0.1/ProgrammersGuideSinglePage.html]].
217
218 === Examples ===
219
220 ==== Example 1 ====
221
222 In this example we'll print calls to ##CommonsConfigurationSource.containsKey(...)## with the parameters printed and the time it takes to execute. In addition we'll also print calls to ##XWiki.getDocument(String, XWikiContext)## which is a deprecated method which, for the purpose of this example, we think generate the calls to ##containsKey##.
223
224 {{code}}
225 RULE Create timer for containsKey
226 CLASS CommonsConfigurationSource
227 METHOD containsKey
228 AT ENTRY
229 IF TRUE
230 DO resetTimer("containsKey")
231 ENDRULE
232
233 RULE Calls to containsKey
234 CLASS CommonsConfigurationSource
235 METHOD containsKey
236 AT EXIT
237 IF TRUE
238 DO traceln("containsKey for [" + $1 + "] = [" + $! + "], time = [" + getElapsedTimeFromTimer("containsKey") + "]")
239 ENDRULE
240
241 RULE Calls to deprecated getDocument
242 CLASS com.xpn.xwiki.XWiki
243 METHOD getDocument(String, XWikiContext)
244 AT ENTRY
245 IF TRUE
246 DO traceStack("getDocument() called for [" + $1 + "] ", 3)
247 ENDRULE
248 {{/code}}
249
250 Generates:
251
252 {{code}}
253 ...
254 getDocument() called for [XWiki.Admin] com.xpn.xwiki.XWiki.getDocument(XWiki.java:-1)
255 com.xpn.xwiki.XWiki.getUserName(XWiki.java:5072)
256 com.xpn.xwiki.XWiki.getUserName(XWiki.java:5062)
257 . . .
258 containsKey for [model.reference.default.document] = [false], time = [0]
259 containsKey for [model.reference.default.document] = [false], time = [0]
260 containsKey for [model.reference.default.space] = [false], time = [0]
261 containsKey for [model.reference.default.space] = [false], time = [0]
262 containsKey for [model.reference.default.wiki] = [false], time = [0]
263 containsKey for [model.reference.default.wiki] = [false], time = [1]
264 getDocument() called for [XWiki.DefaultSkin] com.xpn.xwiki.XWiki.getDocument(XWiki.java:-1)
265 com.xpn.xwiki.XWiki.getSkinFile(XWiki.java:1955)
266 com.xpn.xwiki.XWiki.getSkinFile(XWiki.java:1918)
267 . . .
268 ...
269 {{/code}}
270
271 ==== Example 2 ====
272
273 Log calls to ##XWikiDocument#setLock()## and ##XWikiDocument#removeLock()##.
274
275 {{code}}
276 RULE XWiki Set Lock
277 CLASS XWikiDocument
278 METHOD setLock
279 AT ENTRY
280 IF TRUE
281 DO traceln("set lock for user [" + $1 + "], doc = [" + $this + "]")
282 ENDRULE
283
284 RULE XWiki Remove Lock
285 CLASS XWikiDocument
286 METHOD removeLock
287 AT ENTRY
288 IF TRUE
289 DO traceln("remove lock for doc = [" + $this + "]")
290 ENDRULE
291
292 RULE XWiki Get Lock
293 CLASS XWikiDocument
294 METHOD getLock
295 AT ENTRY
296 IF TRUE
297 DO traceln("get lock for doc = [" + $this + "]")
298 ENDRULE
299 {{/code}}
300
301 When you click edit and then cancel on a doc you get for example:
302
303 {{code}}
304 // Edit
305 get lock for doc = [Sandbox.WebHome]
306 set lock for user [XWiki.Admin], doc = [Sandbox.WebHome]
307 get lock for doc = [Sandbox.WebHome]
308 get lock for doc = [Sandbox.WebHome]
309 set lock for user [XWiki.Admin], doc = [Sandbox.WebHome]
310
311 // Cancel
312 get lock for doc = [Sandbox.WebHome]
313 remove lock for doc = [Sandbox.WebHome]
314 {{/code}}
315
316 When you click edit and then save on a doc you get for example:
317
318 {{code}}
319 // Edit
320 get lock for doc = [Sandbox.WebHome]
321 set lock for user [XWiki.Admin], doc = [Sandbox.WebHome]
322 get lock for doc = [Sandbox.WebHome]
323 get lock for doc = [Sandbox.WebHome]
324 set lock for user [XWiki.Admin], doc = [Sandbox.WebHome]
325
326 // Save
327 get lock for doc = [Sandbox.WebHome]
328 remove lock for doc = [Sandbox.WebHome]
329 get lock for doc = [Sandbox.WebHome]
330 {{/code}}
331
332 === Troubleshooting ===
333
334 ==== NoClassDefFoundError: com/sun/tools/attach/AttachNotSupportedException ====
335
336 If you get the following exception, it can mean that you're on Mac and that your ##tools.jar## is not added to the classpath. Apparently ##bminstall.sh## thinks that if you're on Mac then you don't need ##tools.jar## which is apparently wrong nowadays.
337
338 {{code language="none"}}
339 Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/attach/AttachNotSupportedException
340 at java.lang.Class.getDeclaredMethods0(Native Method)
341 at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
342 at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
343 at java.lang.Class.getMethod0(Class.java:3018)
344 at java.lang.Class.getMethod(Class.java:1784)
345 at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
346 at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
347 Caused by: java.lang.ClassNotFoundException: com.sun.tools.attach.AttachNotSupportedException
348 at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
349 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
350 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
351 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
352 ... 7 more
353 {{/code}}
354
355 In this case, edit ##bminstall.sh## and add the following line below the ##OS=`uname`## line in order to override it:
356
357 {{code language="none"}}
358 OS=whatever
359 {{/code}}
360
361 = Debugging JavaScript =
362
363 The solution is to use the developer tools provided by the Browser for inspecting JavaScript and putting breakpoints in it. By default the XWiki build will minify and aggregate JavaScript files for performance reasons.
364
365 {{version since="12.7-rc-1"}}
366 Open the developer tools provided by the browser and put the breakpoints using the Debugger / Sources tab. Look for the //non-minified// (source) JavaScript code (Ctrl+P). You should be able to find it most of the time because the minified version (which is used by default) indicates its source map which in turn indicates the source code. So the browser ends up loading all 3 when the developer tools are open (shouldn't be the case for end users), which means you can run the minified version while viewing the progress step by step over the source (non-minified) version. If the source map is missing or the source URL is wrong then you can still debug step by step using the source code by adding ##?minify=false## to the URL of the current page. This will force the browser to load the non-minified version (and only that).
367
368 Note that JavaScript minification is not only about removing whitespace and renaming local variables. Depending on the minifier used it may also mean code optimizations, syntax suggar replacement, polyfill injection, etc. So the differences between the minified version and the source code could be significant. As a consequence:
369
370 * debugging step by step may behave strangely when there's no 1 to 1 mapping between the minified code and its source
371 * the non-minified (source) version might not work on all browsers; that's why we recommend using ##?minify=false## only with the latest versions of Firefox and Chrome.
372 {{/version}}
373
374 {{version since="7.1"}}
375 You can also set ##debug.minify## to ##false## in ##xwiki.properties## file instead of passing ##?minify=false## in the URL.
376 {{/version}}
377
378 {{version before="12.7-rc-1"}}
379 You had to do the following:
380 * Build XWiki with the ##debug## profile (##mvn clean install -Pdebug##)
381 * Once you're on a page make sure to pass ##?minify=false## in the URL. If you don't do this then the aggregated JS files are going to be referenced and since they don't exist, the JS code will break.
382 {{/version}}
383
384
385 == Debugging Vue.js ==
386
387 The first step is to load a non-minified version of ##vue.js##. To do so, edit ##webapps/xwiki/resources/uicomponents/widgets/liveData.min.js## and replace {{code}}'vue': $services.webjars.url('vue', 'vue.min'){{/code}} by {{code}}'vue': $services.webjars.url('vue', 'vue'){{/code}}.
388 Then, install [[Vue Devtools>>https://devtools.vuejs.org/]] in Firefox or Chrome.
389 You should now have access to the Vue tab in you browser debugger, with the ability to inspect the Vue applications deployed in the page.
390
391 = Debugging the WYSIWYG editor =
392
393 Example to debug JS code in ##macroSelector.js##:
394
395 * Modify the top level CKEditor ##pom.xml## to remove minification (the important part is to add {{code}}--leave-js-unminified{{/code}} as on the example below):(((
396 {{code language="xml"}}
397 ...
398 <plugin>
399 <groupId>org.codehaus.mojo</groupId>
400 <artifactId>exec-maven-plugin</artifactId>
401 <executions>
402 <!-- Build the CKEditor. -->
403 <execution>
404 <id>build-ckeditor</id>
405 <!-- Use a phase after compile because the Clirr Maven Plugin executes all the phases up to compile twice. -->
406 <phase>process-classes</phase>
407 <goals>
408 <goal>exec</goal>
409 </goals>
410 <configuration>
411 <executable>${ckeditor.builder.path}/build.sh</executable>
412 <arguments>
413 <!-- Exclude from release all plugins/skins that are not specified in build-config. -->
414 <argument>--skip-omitted-in-build-config</argument>
415 <argument>-s --leave-js-unminified</argument>
416 </arguments>
417 </configuration>
418 </execution>
419 </executions>
420 </plugin>
421 ...
422 {{/code}}
423 )))
424 * Rebuild the ##application-ckeditor-webjar## module (you'll also need to rebuild##application-ckeditor-plugins## if you made changes to it).
425 * Copy the generated ##application-ckeditor-webjar-<version>.jar## to an XWiki instance, in ##WEB-INF/lib## and restart XWiki
426 ** You could also remove the CKEditor extensions in the permanent's directory (in ##extensions/repository##) to be safe.
427 * In the wiki, edit ##CKEditor.EditSheet## in object mode and look for ###set ($macroWizardBundlePath = "${ckeditorBasePath}plugins/xwiki-macro/macroWizard.bundle.min")## and remove the ##.min## part. Note that in this case you have to know that the macro wizard is loaded separately in ##macroWizard.bundle.min.js##. Otherwise the JS is in ##ckeditor.js##.
428 * Use your browser's dev tools to put breakpoints in the JS.
429
430 = Analyze Out Of Memory issues =
431
432 You can enable automatic memory dump when using ##-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/where/to/save/the/memory/dumps ## which will generate a memory dump as soon as Java detect an Out Of memory error. See https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/clopts001.html#CHDFDIJI for more details.
433
434 Since 7.2RC1 the option is enabled by default in Jetty based distributions and the memory dump will ends up in ##data/## folder.

Get Connected