Wiki source code of Saving Data

Last modified by Vincent Massol on 2024/09/09

Hide last authors
Vincent Massol 1.1 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 There are times when you wish to save data. The XWiki platform offers various places that you can use depending on your needs. Here's a rundown of all the options you have.
6
7 = Transient Saves =
8
9 == Execution Context ==
10
Manuel Smeria 6.5 11 If the data to be saved should only be saved for the duration of a request (i.e. a call to an XWiki URL) then you should declare a property in the **Execution Context**.
Vincent Massol 1.1 12
13 For example, from Java in a Component:
14
15 {{code language="java"}}
16 import org.xwiki.execution.*;
17
18 @Inject Execution execution;
19 ...
Andreas Jonsson 6.1 20 // Declaring
Vincent Massol 1.1 21 ExecutionContext ec = execution.getContext();
Andreas Jonsson 6.1 22 ec.newProperty("mykey").initial(initialValue).declare();
Vincent Massol 1.1 23 ...
Andreas Jonsson 6.1 24 // Updating
25 ec.setProperty("mykey", newValue);
26 ...
Vincent Massol 1.1 27 // Retrieving
28 Object myvalue = e.getProperty("mykey");
29 {{/code}}
30
Andreas Jonsson 6.4 31 === Execution Context Property Declaration ===
32
Manuel Smeria 6.5 33 The declaration is currently optional, the property will be implicitly declared when set the first time. The declaration can be made in an ##ExecutionContextInitializer## component. The initialize method of all such components that are available in the classpath and have been specified in a ##components.txt## file will be called when the execution context is first initialized during the request.
Andreas Jonsson 6.1 34
35 {{code language="java"}}
36 import org.xwiki.context.ExecutionContext;
37 import org.xwiki.context.ExecutionContextInitializer;
38 import org.xwiki.context.ExecutionContextException;
39 import org.xwiki.component.annotation.Component;
40
41 @Component
42 public class DeclareMyPropertyExecutionContextInitializer implements ExecutionContextInitializer
43 {
44 @Override
45 public void initialize(ExecutionContext executionContext)
46 {
Andreas Jonsson 6.2 47 if (!executionContext.hasProperty("mykey")) {
48 executionContext.newProperty("mykey").type(String.class).nonNull().initial("").declare();
Andreas Jonsson 6.1 49 }
50 }
51 }
52 {{/code}}
53
54 In the above example you can see that it is possible to set various attributes on the property when it is beeing declared. The attributes currently supported are listed in the table below.
55
56 During a request cycle, some components may activate a //clean// or a //cloned// execution context by pushing to the execution context stack. You can control how you want your property to be managed in these situations by setting attributes.
57
Andreas Jonsson 6.3 58 |=(% style="width:25%" %)Attribute |=Parameters |=Description
Manuel Smeria 6.5 59 |cloneValue()| - |Indicate that you want the value to be cloned when the execution context is cloned or when your property is inherited from a parent execution context
60 |makeFinal()| - |Indicate that an exception should be thrown if someone tries to replace the initial value object
61 |inherited()| - |Indicate that the property should be inherited by any new execution context that is pushed within the current request
62 |nonNull()| - |Indicate that an exception should be thrown if ##null## is set as the property value
Andreas Jonsson 6.3 63 |type(Class<?> type)|(((
Andreas Jonsson 6.1 64 ; type
65 : the class that the value object should be typechecked against
Andreas Jonsson 6.3 66 )))|Set a type for performing typechecking when updating the value object.
Andreas Jonsson 6.1 67
Andreas Jonsson 6.4 68 === Wiki Page Access to Execution Context ===
69
Manuel Smeria 6.5 70 {{info}}
Thomas Mortagne 7.1 71 We currently [[cannot access easily the Execution Context from a wiki page>>https://jira.xwiki.org/browse/XCOMMONS-242]] but this should be improved. Currently it's not available from Velocity, but it is from Groovy.
Manuel Smeria 6.5 72 {{/info}}
Vincent Massol 1.1 73
Manuel Smeria 6.5 74 From a wiki page:
75
Vincent Massol 1.1 76 {{code}}
77 {{groovy}}
78 import org.xwiki.context.*
79
80 def ec = services.component.getInstance(Execution.class).getContext()
81 ec.setProperty("mykey", myvalue)
82 {{/groovy}}
83 {{/code}}
84
Manuel Smeria 6.5 85 {{info}}
86 From a wiki page it's much easier to use the older **XWiki Context** (which is supposed to be fully replaced by the Execution Context at some point in the future).
87 {{/info}}
Vincent Massol 1.1 88
Manuel Smeria 6.5 89 For example:
90
Vincent Massol 1.1 91 {{code}}
92 {{velocity}}
93 $xcontext.put("mykey", value)
94 {{/velocity}}
95 {{/code}}
96
Vincent Massol 8.1 97 {{warning}}
98 This requires Programming Rights.
99 {{/warning}}
100
Manuel Smeria 6.5 101 {{info}}
102 It's also possible to save data in the HTTP Request even though it's recommended to use the Execution Context instead (since the Execution Context is independent of the execution environment and will work everywhere: Servlets, Portlets, JavaSE, etc).
103 {{/info}}
Vincent Massol 4.1 104
Manuel Smeria 6.5 105 For example from Velocity in a wiki page:
106
Vincent Massol 4.1 107 {{code}}
108 {{velocity}}
109 $request.setAttribute("mykey", value)
110 {{/velocity}}
111 {{/code}}
112
Vincent Massol 1.1 113 == Servlet Session ==
114
Vincent Massol 4.1 115 If the data should last a little longer (i.e. for example span more than 1 request), you could save it in the Servlet Session (note that in this case your code will only work in a Servlet Environment).
Vincent Massol 1.1 116
117 For example, from Java in a Component:
118
119 {{code language="java"}}
120 import org.xwiki.container.*;
121
122 @Inject Container container;
123 ...
124 Request request = container.getRequest();
125 // Note that this is a bit of a hack and the notion of Session exists in the Container class (getSession()) but the Session interface is empty at the moment, making it useless)
126 if (request instanceof ServletRequest) {
127 HttpServletRequest servletRequest = (ServletRequest) request;
128 HttpSession session = servletRequest.getSession();
129 session.setAttribute("mykey", myvalue);
130 }
131 {{/code}}
132
Vincent Massol 5.1 133 Example from a wiki page:
134
135 {{code}}
136 {{velocity}}
137 $request.getSession().setAttribute("mykey", myvalue)
138 {{/velocity}}
139 {{/code}}
140
Vincent Massol 1.1 141 == Temporary Directory ==
142
Manuel Smeria 6.5 143 If the data should last even a little longer than a session, you could save it in a file in the environment's temporary directory.
Vincent Massol 1.1 144
145 For example, from Java in a Component:
146
147 {{code language="java"}}
148 import org.xwiki.environment.*;
149 import org.apache.commons.io.*;
150
151 @Inject Environment environment;
152 ...
153 File tmpDir = environment.getTemporaryDirectory();
154 FileUtils.write(tmpDir, "something");
155 {{/code}}
156
157 == Servlet Context ==
158
Vincent Massol 4.1 159 If the Data should last as long as the web application is up, you could use the Servlet Context. It's not very easy to access it but it's possible (note that in this case your code will only work in a Servlet Environment).
Vincent Massol 1.1 160
161 For example, from Java in a Component:
162
163 {{code language="java"}}
164 import org.xwiki.container.*;
165 import com.xpn.xwiki.*;
166 import com.xpn.xwiki.web.*;
167
168 @Inject Execution execution;
169 ...
170 // Get the older XWiki Context
171 XWikiContext xc = (XWikiContext) execution.getContext().getProperty("xwikicontext");
172 XWikiEngineContext ec = xc.getEngineContext();
173 ec.setAttribute("mykey", myvalue);
174 {{/code}}
175
Vincent Massol 10.1 176 == Using the Cache API ==
177
178 You can also create a Cache and store data in it. See the [[Cache API>>extensions:Extension.Cache Module]].
179
Vincent Massol 1.1 180 = Permanent Saves =
181
182 == Wiki Model ==
183
Simon Urli 9.5 184 The best place to save data is usually in the wiki itself (See the [[Data Model>>xwiki:Documentation.DevGuide.DataModel]] and the [[API Guide>>xwiki:Documentation.DevGuide.APIGuide]] for some examples). There are several places where you can store data in the model:
Andreas Jonsson 6.1 185
Manuel Smeria 6.5 186 * In the document content itself
187 * In an XObject attached to a document
188 * In an attachment
Vincent Massol 1.1 189
190 == Permanent Directory ==
191
Manuel Smeria 6.5 192 Another possibility is to use the environment's permanent directory.
Vincent Massol 1.1 193
194 For example, from Java in a Component:
195
196 {{code language="java"}}
197 import org.xwiki.environment.*;
198 import org.apache.commons.io.*;
199
200 @Inject Environment environment;
201 ...
202 File permDir = environment.getPermanentDirectory();
203 FileUtils.write(permDir, "something");
204 {{/code}}

Get Connected