Wiki source code of WritingComponents

Version 18.1 by JeromeVelociter on 2009/03/21

Show last authors
1 1 Writing XWiki components
2
3 #toc("", "", "")
4
5 This tutorial will guide you through the creation of an XWiki component that will soon replace the plugins architecture and which is now the recommended way of writing XWiki modules. They should be able to execute any java code and communicate with XWiki by using the existing XWiki (core) components, as well as being exposed to the xwiki documents scripting environment (velocity and groovy).
6
7 1.1 What are Components?
8
9 First, you should know a few things about [Plexus > http://plexus.codehaus.org/] engine and [component based architecture > http://plexus.codehaus.org/ref/why-use-components.html]. In very few words, component based architecture is a design principle based on low-coupling / high-cohesion pattern, with components (modules) focused on a single "job" in the system, that describe themselves through interfaces (services) and communicate with other components through these "contracts", without any concern about the implementation. The key is in the components engine (or manager) that handles instantiation and components dependency, based on each component's declaration of these (in its description file), automatically injecting the implementations at runtime.
10
11 So, what we should do in order to write a component is:
12 * define the service the component "provides" (the interface). This interface is all that the component will expose to the other components. Any function you should need to ask to your component goes here.
13 * create one or more implementations for this service. Of course, you must ~~actually provide~~ the services you described earlier
14 * register the implementation and the interface in the <tt>components.xml</tt> file (<tt>META-INF/plexus/components.xml</tt>), as well as the dependencies on other components, requirements and other configurations for your component.
15
16
17
18
19
20 1.1 XWiki Specifics
21
22 In XWiki, although we use the [Plexus>http://plexus.codehaus.org/] engine for the moment, we don't want to depend on the Plexus implementation (because we should be able to change components engine anytime, if we wanted to) so we have our own set of lifecycle interfaces to communicate with the manager:
23 * [org.xwiki.component.phase.Initializable>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-component/apidocs/org/xwiki/component/phase/Initializable.html]: allows the <tt>initialize</tt> method of a component to be called when it's first initialized
24 * [org.xwiki.component.phase.Composable>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-component/apidocs/org/xwiki/component/phase/Composable.html]: allows injecting the component manager in a component. Note that component requirements should usually be defined as private field members and defined in <tt>components.xml</tt>. The need for <tt>Composable</tt> is very specific, usually when you need to iterate over some component list, or query various implementations for a component at runtime.
25 * [org.xwiki.component.phase.LogEnabled>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-component/apidocs/org/xwiki/component/phase/LogEnabled.html]: for getting a logger. Usually you should extend the [AbstractLogEnabled>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-component/apidocs/org/xwiki/component/logging/AbstractLogEnabled.html] class to hide the logging setup code.
26
27 All these are defined in the [xwiki-component module in platform/core>https://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-component/].
28
29
30
31 1.1 Let's get started!
32
33 Enough talking, let's see some code!
34
35 In the followings we will guide you through writing a simple component, helping you to quickly get oriented in XWiki components world and explaining how it works.
36
37 1.1.1 Creating a XWiki component using maven
38
39 To simplify the three steps process of component creation in XWiki, and since the XWiki code lifecycle is based on [maven>http://maven.apache.org/], we have created a maven archetype to help create a simple component module with a single command, with respect to the XWiki architecture and components specific requirements.
40 * download the archetype from here: {attach:xwiki-archetype-component-1.0-SNAPSHOT.jar} (it will soon be uploaded on our maven repository).
41 * use maven to install this file on your local repository by executing (make sure you replace <tt>path-to-jar-file</tt> with your own path):
42 {code}
43 mvn install:install-file -Dfile=<path-to-jar-file> -DartifactId=xwiki-archetype-component -DgroupId=com.xpn.xwiki.platform.tools -Dversion=1.0-SNAPSHOT -Dpackaging=jar
44 {code}
45 * now you're ready to use maven to generate the xwiki component based on this archetype. Navigate to the directory where you want your component to be located and type:
46 {code}
47 mvn archetype:generate -DarchetypeGroupId=com.xpn.xwiki.platform.tools -DarchetypeArtifactId=xwiki-archetype-component -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=<component-group-id> -DartifactId=<component-artifact-id> -Dpackage=<component-package> -Dversion=<component-version> -Dpackaging=jar
48 {code}
49 where you replace <tt>component-group-id</tt>, <tt>component-artifact-id</tt>, <tt>component-package</tt>, <tt>component-version</tt> with the corresponding values for your component. To create a server XWiki Watch component, for example, we used <tt>-DgroupId=com.xpn.xwiki.products -DartifactId=xwiki-watch-component -Dpackage=org.xwiki.watch.component -Dversion=1.1-SNAPSHOT</tt>. Don't forget to follow the [xwiki package names guidelines > http://dev.xwiki.org/xwiki/bin/view/Community/CodeStyle#HPackagenames-1].
50
51 Now this will create a new maven module in a folder named <tt>component-artifact-id</tt> in your folder, with a default xwiki component inside.
52 #info("Note that if your parent (current, from where you are executing maven) folder is the folder of a maven module (contains a <tt>pom.xml</tt> file), then the command above will fail unless the module is packaged as <tt>pom</tt>. If the project is packaged as <tt>pom</tt>, then the newly created module will be added in its modules list, and the parent of the newly created component module will be set to this project's <tt>pom</tt>.")
53
54 1.1.1 The component explained
55
56 Assume, for the following explanations, that the package you used is <tt>org.xwiki.component</tt>
57
58 Navigating in the component project folder, you will see standard maven project structure like this:
59 {code}
60 pom.xml
61 src/main/java/org/xwiki/component/HelloWorld.java
62 src/main/java/org/xwiki/component/internal/DefaultHelloWorld.java
63 src/main/resources/META-INF/plexus/components.xml
64 src/test/java/org/xwiki/component/HelloWorldTest.java
65 {code}
66 which corresponds to the default files created: the <tt>HelloWorld</tt> interface (service), its implementation <tt>DefaultHelloWorld</tt>, a test class for this component <tt>HelloWorldTest</tt>, the component description file <tt>components.xml</tt> and the maven project <tt>pom</tt> file.
67
68 If we have a look in the <tt>pom</tt>, we see something like this:
69 {code}
70 <groupId>your-group-id</groupId>
71 <artifactId>your-artifact-id</artifactId>
72 <version>your-version</version>
73 {code}
74 which are the group, artifact and version you used when you created your component
75 {code}
76 <properties>
77 <!-- TODO: remove this if you inherit a project that has the core version set -->
78 <platform.core.version>1.8-SNAPSHOT</platform.core.version>
79 </properties>
80 {code}
81 used to define the core version for the xwiki-component dependency. If your component is created as part of a project already depending on the core (and which most probably already has a property for the core version), use the inherited property value instead of redefining it here. Or, if the component should have the same version as the rest of the XWiki modules, you can use <tt>${pom.version}</tt> as the version for other XWiki dependencies.
82 {code}
83 <dependencies>
84 <dependency>
85 <groupId>org.xwiki.platform</groupId>
86 <artifactId>xwiki-core-component</artifactId>
87 <version>${platform.core.version}</version>
88 </dependency>
89 <dependency>
90 <groupId>junit</groupId>
91 <artifactId>junit</artifactId>
92 <version>3.8.1</version>
93 <scope>test</scope>
94 </dependency>
95 <!-- Add here all your other dependencies -->
96 </dependencies>
97 {code}
98 which define the dependency on the xwiki-component module in the core and the junit for the testing phase and, of course, marks the spot for you to add all your other components, modules, and libraries dependencies for maven to know and put them on your classpath when compiling, etc.
99
100 The interface file (<tt>HelloWorld.java</tt>) contains the definition of a regular Java interface, with a special <tt>ROLE</tt> field
101 {code}
102 /** The role associated with the component. */
103 String ROLE = HelloWorld.class.getName();
104 {code}
105 which associates a name (that would identify a functionality, concern) to this service. Keep in mind that only this interface specifies the functions the other components will use to communicate with our component, no other functions besides the ones defined in this interface will be accessible to the "outside world". In our case, we'll build a polite component that can only <tt>sayHello()</tt>.
106
107 You can find more information about components identity in plexus at [http://plexus.codehaus.org/guides/developer-guide/building-components/component-identity.html].
108
109 Then we have the implementation of the interface, the <tt>DefaltHelloWorld</tt> class.
110 {code}
111 public class DefaultHelloWorld extends AbstractLogEnabled implements HelloWorld, Initializable
112 {code}
113 it extends <tt>AbstractLogEnabled</tt> to be able to use the logging system, implements the component interface, and also the <tt>Initializable</tt> interface which allows it to hook initialization code upon its instantiation by the component manager, in the <tt>initialize()</tt> function:
114 {code}
115 public void initialize() throws InitializationException
116 {
117 //TODO: initialize component
118 // getLogger is inherited from AbstractLogEnabled
119 getLogger().debug("DefaultHelloWorld initialized");
120 }
121 {code}
122
123 We also find a field that contains the greeting to be used and the implementation of the <tt>sayHello()</tt> function in the interface:
124 {code}
125 /** The greeting that was specified in the configuration. */
126 private String greeting;
127
128 /**
129 * Says hello by returning a greeting to the caller.
130 *
131 * @return A greeting.
132 */
133 public String sayHello()
134 {
135 return greeting;
136 }
137 {code}
138
139 The very interesting part of all the project, which gives all the salt and pepper to our component, is the description file, <tt>components.xml</tt>:
140 {code}
141 <component-set>
142 <components>
143 <component>
144 <role>org.xwiki.component.HelloWorld</role>
145 <implementation>org.xwiki.component.internal.DefaultHelloWorld</implementation>
146 <configuration>
147 <!-- injected in the greeting field in the implementation -->
148 <greeting>Hello World!</greeting>
149 </configuration>
150 </component>
151 </components>
152 </component-set>
153 {code}
154 which basically tells Plexus to use the implementation in the <tt>DefaultHelloWorld</tt> class to provide the service defined by the <tt>HelloWorld</tt> interface. Note that the role can have any value as long as it uniquely identifies a role, we use as convention the name of the service interface. The <tt>configuration</tt> element of the component allows us to specify the set of configurations to be injected by the component manager at runtime, for the implementation: in our case, the greeting to be used, which will be mapped on the <tt>greeting</tt> field in the class.
155
156 A more detailed guide through the <tt>components.xml</tt> file can be found at http://plexus.codehaus.org/guides/developer-guide/configuration/component-descriptor.html and http://plexus.codehaus.org/ref/component-configuration.html
157
158
159 1.1 How to find my component and use it?
160
161 1.1.1 From other components
162
163 To access your component from another component we use the components engine, and specify the dependencies declarative, leaving instantiation and component injection to the be handled by the component manager. The most straightforward way is the use of the requirements mechanism of plexus, specifying that our component is required by the component that needs to access it.
164
165 Don't forget that any code that uses the component we wrote needs to have the component interface accessible in its classpath. Even if instantiation and dependency is handled by the engine at runtime, the code still needs to compile.
166 If the two components are not in the same module (the same .jar), don't forget to add the module of the greeter component as a dependency of the module of any component that uses it.
167
168 Then, to effectively use the <tt>HelloWorld</tt> component, we need a reference to it in the the component that uses it. For this, we use a member variable in the implementation of the using component, for example, a <tt>Socializer</tt> component will need to be able to say hello to the world:
169 {code}
170 public class DefaultSocializer extends AbstractLogEnabled implements Socializer, Initializable
171 {
172 [...]
173
174 /** Will be injected by the component manager */
175 private HelloWorld helloWorld;
176
177 [...]
178 }
179 {code}
180
181 Then, we need to tell Plexus about this dependency so that it assignes a <tt>HelloWorld</tt> instance to the <tt>helloWorld</tt> variable, at runtime. For this, we use the components specification file of the <tt>Socializer</tt> component, which would look something like this:
182 {code}
183 <component-set>
184 <components>
185 <component>
186 <role>org.xwiki.component.Socializer</role>
187 <implementation>org.xwiki.component.internal.DefaultSocializer</implementation>
188 <requirements>
189 <requirement>
190 <role>org.xwiki.component.HelloWorld</role>
191 </requirement>
192 </requirements>
193 </component>
194 </components>
195 </component-set>
196 {code}
197
198 Note the <tt>requirements</tt> element, which contains a requirement for the <tt>HelloWorld</tt> role, that the <tt>HelloWorld</tt> component provides.
199
200 And that's it, you can now use the <tt>helloWorld</tt> member anywhere in the <tt>DefaultSocializer</tt> class freely, without further concerns, it will be assigned by the component manager provided that the <tt>HelloWorld</tt> component is on the classpath at runtime when the <tt>Socializer</tt> is used. Such as:
201
202 {code}
203 public class DefaultSocializer extends AbstractLogEnabled implements Socializer, Initializable
204 {
205 [...]
206
207 public void startConversation()
208 {
209 this.helloWorld.sayHello();
210
211 [...]
212 }
213
214 [...]
215 }
216 {code}
217
218 More, note that all through the process of defining a communication path between two components, we never referred components implementations, all specifications being done through ~~roles~~ and ~~interfaces~~: the implementation of a service is completely hidden from any code external to the component.
219
220 TODO: refer to the other ways of implementing dependencies but requirements mechanism. Details, explanations, links.
221
222 1.1.1 From non-components java code (e.g. older plugins)
223
224 For this kind of usages, since we cannot use the component-based architecture advantages and the "magic" of the component manager, the XWiki team has created a helper method that acts like a bridge between component code and non-component code, the <tt>com.xpn.xwiki.web.Utils.getComponent(String role, String hint)</tt> that gets the specified component instance from the component manager and returns it. The hint is an optional identifier, additional to <tt>role</tt>, used to differentiate between implementations of the same interface: the ~~roles~~ identify services while the hints help differentiate between implementations (see more at [http://plexus.codehaus.org/guides/developer-guide/building-components/component-identity.html > http://plexus.codehaus.org/guides/developer-guide/building-components/component-identity.html]). The <tt>getComponent</tt> function also has a version without the <tt>hint</tt> parameter, that uses the default hint.
225
226 To use our greetings provider component, we simply invoke:
227 {code}
228 HelloWorld greeter = (HelloWorld) Utils.getComponent(HelloWorld.ROLE);
229 //use the HelloWorld service
230 greeter.sayHello();
231 {code}
232
233 Note that, even if, in fact, the object returned by this function is an instance of the DefaultHelloWorld, you should *never declare your object of the implementation type nor cast to implementation instead of interface*. A component is represented by its interface, the implementation for such a service can be provided by any code, any class so relying on the implementation type is nor good practice (since the interface contract should be enough for a component), nor safe. In the future, a maven enforcer plugin will be setup in the build lifecycle, so that any reference to component implementations (located in an "internal" subpackage) will cause build errors.
234
235 #info("The usage of <tt>Utils.getComponent()</tt> functions is highly discouraged, reserved for this type of situations, when you need to access a component from non-componentized code. For the componentized code, you should use either dependency declaration at 'compile-time' (in components.xml files) or, if you need to resolve components dependencies at runtime, use the ComponentManager, which you can access by implementing the Composable interface described above.")
236
237 1.1.1 From wiki pages
238
239 In order to use a component in wiki pages, we need to expose it to the scripting environments: groovy and velocity.
240
241 1.1.1.1 Accessing a component from groovy
242
243 Since, in groovy, we have access to all classes and functions in XWiki (all this protected by the requirement for programming rights), it means that we can use the same method as in [the previous section > WritingComponents#HFromnoncomponentsjavacode28egolderplugins29], using the <tt>Utils</tt> class. A simple page that would print the greeting from the <tt>HelloWorld</tt> component would look like this (of course, with your own package for the HelloWorld interface):
244
245 {code}
246 <%
247 def greeter = com.xpn.xwiki.web.Utils.getComponent(org.xwiki.component.HelloWorld.ROLE);
248 println greeter.sayHello();
249 %>
250 {code}
251
252 TODO: talk about the future plans (?) to make a component accessible in the groovy context through a groovy bridge.
253
254 1.1.1.1 Accessing a component from velocity
255
256 XWiki dev team is currently working on the design of a VelocityBridge interface that will handle components access from velocity. Until this specification is ready and its first implementation done, we can do it as follows:
257
258 We write another component in our package, that implements the <a href="http://svn.xwiki.org/svnroot/xwiki/platform/core/trunk/xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextInitializer.java"><tt>VelocityContextInitializer</tt></a>, which is responsible for the initialization of the velocity context in XWiki through its method <tt>initialize(VelocityContext context)</tt>, called automatically when a new velocity context is created. As you probably guessed, we will use this function to add our <tt>HelloWorld</tt> component to the velocity context.
259
260 {code}
261 public class HelloWorldVelocityContextInitializer implements VelocityContextInitializer
262 {
263 /** The key to add to the velocity context */
264 public static final String VELOCITY_CONTEXT_KEY = "greeter";
265
266 /** The component instance to add to the velocity context, injected by the component manager */
267 private HelloWorld helloWorld;
268
269 /**
270 * Add the component instance to the velocity context received as parameter.
271 */
272 public void initialize(VelocityContext context)
273 {
274 context.put(VELOCITY_CONTEXT_KEY, this.helloWorld);
275 }
276 }
277 {code}
278
279 The result of this will be the availability of the <tt>HelloWorld</tt> instance in velocity through the key ~~greeter~~ (as in <tt>$greeter.sayHello()</tt>).
280
281 Of course, we need to have our <tt>HelloWorld</tt> component reference when we execute this code so we add it as a dependency to this velocity context initializer component, as described in [the section above>#HFromothercomponents]:
282 {code}
283 <component>
284 <role>org.xwiki.velocity.VelocityContextInitializer</role>
285 <role-hint>greeter</role-hint>
286 <implementation>org.xwiki.component.internal.vcinitializer.HelloWorldVelocityContextInitializer</implementation>
287 <instantiation-strategy>singleton</instantiation-strategy>
288 <requirements>
289 <requirement>
290 <role>org.xwiki.component.HelloWorld</role>
291 </requirement>
292 </requirements>
293 </component>
294 {code}
295
296 This code goes in the <tt>components.xml</tt> file of the package where the velocity context initializer is located. In our case, in the same file as the description for the <tt>HelloWorld</tt> is.
297
298 Note that this time, we also use roles for component identification, because we need to differentiate this implementation of the <tt>VelocityContextInitializer</tt> from the other implementations, as it is not the only component with this role in XWiki. Also note an <tt>instantion-strategy</tt> that tells Plexus to instantiate this component only once.
299
300 Of course, in order to for all this to compile, we need to have the <tt>VelocityContextInitializer</tt> interface available on the classpath so we have this new dependency in the component module's pom:
301 {code}
302 <dependency>
303 <groupId>org.xwiki.platform</groupId>
304 <artifactId>xwiki-core-velocity</artifactId>
305 <version>${platform.core.version}</version>
306 </dependency>
307 {code}
308
309 And that's it, you have made your <tt>HelloWorld</tt> component velocity-accessible! Just recompile your package, copy it in the WEB-INF/lib folder of your xwiki webbapp container, and restart the server. You'll be able to get a greeting in velocity through:
310 {code}
311 $greeter.sayHello()
312 {code}
313
314 For the automatic creation of a velocity accessible xwiki component through this method, we have also created a maven archetype for this purpose too, the {attach:xwiki-archetype-velocity-component-1.0-SNAPSHOT.jar}. Download it and use it as described in [the first part of this tutorial > WritingComponents#HCreatingaXWikicomponentusingmaven].
315
316
317
318
319
320
321
322
323
324 1.1 How do I find other code?
325
326 1.1.1 Other components
327
328 To use other components, you follow the same paradigm explained in the [previous section > WritingComponents#HFromothercomponents] but this time adding the other components as a dependency of the <tt>HelloWorld</tt> component, in its <tt>components.xml</tt> file and having it injected in a member field of the <tt>HelloWorld</tt> implementation. For example, we could have such a dependency:
329
330 {code}
331 public class DefaultHelloWorld extends AbstractLogEnabled implements HelloWorld, Initializable
332 {
333 /** Will be injected by the component manager */
334 private Localizer localizer;
335
336 /** The greeting that was specified in the configuration. */
337 private String greeting;
338
339 /**
340 * Says hello by returning a greeting to the caller.
341 *
342 * @return A greeting.
343 */
344 public String sayHello()
345 {
346 // Get the localized version for the needed greeting
347 return localizer.get(this.greeting);
348 }
349 }
350 {code}
351
352 {code}
353 <component-set>
354 <components>
355 <component>
356 <role>org.xwiki.component.HelloWorld</role>
357 <implementation>org.xwiki.component.internal.DefaultHelloWorld</implementation>
358 <configuration>
359 <!-- bundle key for the greeting to provide -->
360 <greeting>greetings.hello</greeting>
361 </configuration>
362 <!-- the greeter requires a localization component -->
363 <requirements>
364 <requirement>
365 <role>org.xwiki.component.Localizer</role>
366 </requirement>
367 </requirements>
368 </component>
369 </components>
370 </component-set>
371 {code}
372 if we needed to implement a polyglot greeter component.
373
374 1.1.1 The XWiki data model
375
376 Since the XWiki data model (documents, objects, attachments, etc.) reside in the big, old <tt>xwiki-core</tt> module, and since we don't want to add the whole core and all its dependencies as a dependency of a simple lightweight component (this would eventually lead to a circular dependency, which is not allowed by maven), the current strategy, until the data model is completely turned into a component, is to use a ~~bridge~~ between the new component architecture and the old <tt>xwiki-core</tt>.
377
378 In short, the way this works is based on the fact that implementations for a component don't have to be in the same <tt>.jar</tt> as the interface, and there is no dependency ~~from~~ the component interface ~~to~~ the actual implementation, only the other way around. So, we made a few simple components that offer basic access to XWiki documents, and declared the classes in <tt>xwiki-core</tt> as the default implementation for those components.
379
380 If your component needs to access the XWiki data model, it will use the components from the <tt>xwiki-core-bridge</tt> module for that. Note that these interfaces are rather small, so you can't do everything that you could with the old model. If you need to add some methods to the bridge, feel free to propose it on the [mailing list>dev:Community.MailingLists].
381
382 For example:
383 {code}
384 public class DefaultHelloWorld implements HelloWorld
385 {
386 /** Provides access to documents. Injected by the Component Manager. */
387 private DocumentAccessBridge documentAccessBridge;
388
389 [...]
390
391 private String getConfiguredGreeting()
392 {
393 return documentAccessBridge.getProperty("XWiki.XWikiPreferences", "greeting_text");
394 }
395 {code}
396
397 1.1.1 The XWiki context
398
399 Note that the XWiki context is deprecated. It was an older way of keeping track of the current request, which had to be passed around from method to method, looking like a [ball and chain>http://en.wikipedia.org/wiki/Ball_and_chain] present everywhere in the code.
400
401 In the component world, the current request information is held in an *[execution context>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-context/apidocs/org/xwiki/context/ExecutionContext.html]*. This is actually more powerful than the old XWiki context, as it is a generic execution context, and you can create one anytime you want and use it anyway you want. And you don't have to manually pass it around with all method calls, as execution contexts are managed by the *[Execution component>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-context/apidocs/org/xwiki/context/Execution.html]*, which you can use just like any other XWiki component.
402
403 In short, if you want to get access to the execution context (which holds context information inserted by the new components), you must declare a requirement on the <tt>Execution</tt> component (located in the <tt>xwiki-core-context</tt> module), and then you can write:
404 {code}
405 /** Provides access to the request context. Injected by the Component Manager. */
406 private Execution execution;
407
408 [...]
409
410 private void workWithTheContext()
411 {
412 ExecutionContext context = execution.getContext();
413 // Do something with the execution context
414 }
415 {code}
416
417 If you still need to access the old XWiki context, then you can get a reference to it from the execution context, but you should not cast it to an <tt>XWikiContext</tt>, which would pull the whole xwiki-core as a dependency, but to a <tt>Map</tt>. You won't be able to access all the properties, like the current user name or the URL factory, but you can access anything placed in the internal map of the XWikiContext.
418 {code}
419 private void workWithTheContext()
420 {
421 ExecutionContext context = execution.getContext();
422 Map<Object, Object> xwikiContext = (Map<Object, Object>) context.getProperty("xwikicontext");
423 // Do something with the XWiki context
424 }
425 {code}
426
427 If you want not just to use the execution context, but to make something available in every execution context, you can create an implementation of the [ExecutionContextInitializer>http://maven.xwiki.org/site/xwiki-core-parent/xwiki-core-context/apidocs/org/xwiki/context/ExecutionContextInitializer.html] component, and populate newly created execution contexts, just like with [velocity contexts>#HAccessingacomponentfromvelocity].
428
429 1.1.1 Code outside components
430
431 You can use external libraries as in any other maven module, just declare the right dependencies in your module's <tt>pom.xml</tt>.
432
433 As a general rule, you should *not* work with any non-componentized XWiki code, as the way the old code was designed leads to an eventual dependency on the whole <tt>xwiki-core</tt> module, which we are trying to avoid. If the component you are writing is needed by other modules (which is the case with most components, since a component which isn't providing any usable/used services is kind of useless), then this will likely lead to an eventual cyclic dependency, which will break the whole build.
434
435 If you need some functionality from the old core, consider rewriting that part as a new component first, and then use that new component from your code. You should ask first on the [devs mailing list>dev:Community.MailingLists], so that we can design and implement it collaboratively.
436
437 If the effort needed for this is too large, you can try creating a bridge component, by writing just the interfaces in a new module, and make the classes from the core the default implementation of those interfaces. Then, since in the end the xwiki-core, the bridge component and your component will reside in the same classpath, plexus will take care of coupling the right classes. Be careful when writing such bridges, as they are short lived (since in the end all the old code will be replaced by proper components), and if the future real component will have a different interface, then you will have to rewrite your code to adapt to the new method names, or worse, the new component logic.

Get Connected