View Javadoc
1   /*
2    * JBoss, Home of Professional Open Source
3    * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
4    * contributors by the @authors tag. See the copyright.txt in the
5    * distribution for a full listing of individual contributors.
6    *
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * http://www.apache.org/licenses/LICENSE-2.0
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.jboss.as.quickstarts.xa;
18  
19  import javax.inject.Inject;
20  import javax.servlet.ServletException;
21  import javax.servlet.annotation.WebServlet;
22  import javax.servlet.http.HttpServlet;
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  import java.io.IOException;
26  import java.io.PrintWriter;
27  
28  /**
29   * <p>
30   * A servlet for triggering the update of a database and a JMS producer within a single XA transaction.
31   * </p>
32   *
33   * <p>
34   * The servlet is registered and mapped to /XA using the {@linkplain WebServlet
35   * @HttpServlet}. The {@link XAService} is injected by CDI.
36   * </p>
37   *
38   * @author Michael Musgrove
39   *
40   */
41  @SuppressWarnings("serial")
42  @WebServlet("/XA")
43  public class XAServlet extends HttpServlet {
44  
45      private static String PAGE_HEADER = "<html><head><title>jta-crash-recovery</title></head><body>";
46  
47      // page content describing the quickstart and providing a form to perform basic operations against a database
48      private static String PAGE_CONTENT = "<h2>XA Recovery</h2>" +
49              "<p>This quickstart demonstrates how to atomically update multiple resources within one XA transaction. " +
50              "It updates a relational database table using JPA and sends a message using JMS. " + 
51              "In this example, you can perform the following operations:</p>" +
52              "<ul>" + 
53              "<li>To add a <b>key</b>/<b>value</b> pair, enter values in the input text boxes and click <i>Submit</i></li>" +
54              "<li>To update a <b>key</b>/<b>value</b> pair, enter the key and click <i>Submit</i></li>" +
55              "<li>To delete a <b>key</b>/<b>value</b> pair, enter the key and click <i>Delete</i></li>" +
56              "<li>To delete all <b>key</b>/<b>value</b> pairs, leave the key blank and click <i>Delete</i></li>" +
57              "<li>To list the existing <b>key</b>/<b>value</b> pairs, leave the key blank and click <i>Submit</i></li>" +
58              "<li>The refresh the list, click the <i>Refresh Table</i> link.</li>" +
59              "</ul>" +
60  
61              "<p>To demonstrate XA recovery, you will take the following steps:</p> " +
62              "<ol>" +
63              "<li>Add a <b>key</b>/<b>value</b> as described above.</li>" +
64              "<li>Stop the JBoss server.</li>" +
65              "<li>Clear any transaction objectstore data remaining from previous tests.</li>" +
66              "<li>Configure Byteman to halt the JBoss server.</li>" +
67              "<li>Start the JBoss server.</li>" +
68              "<li>Add another <b>key</b>/<b>value</b>. This will cause Byteman to halt the JBoss server.</li>" +
69              "<li>Verify the database record.</li>" +
70              "<li>Disable Byteman.</li>" +
71              "<li>Start the JBoss server.</li>" +
72              "<li>View the resulting recovered row in the table, indicated by the text \"<i>updated via JMS</i>\".</li>" +
73              "</ol>"+
74              "</p> " +
75              "<p>See the README file located in the root of <i>jta-crash-rec</i> folder in the quickstart distribution " +
76              "for complete instructions and details about how this quickstart works.</p> " +
77   
78             "<form>" +
79              "Key: <input type=\"text\" name=\"key\" />" +
80              "&nbsp;(Leave blank to list all key/value pairs).<br />" +
81              "Value: <input type=\"text\" name=\"value\" /><br />" +
82              "<input type=\"submit\" name=\"submit\" value=\"Submit\" />" +
83              "&nbsp;Add or update a pair (or list all pairs if key is blank).<br />" +
84              "<input type=\"submit\" name=\"submit\" value=\"Delete\" />" +
85              "&nbsp;Delete a pair (or all pairs if key is blank).<br />" +
86              "</form>" +
87              "<p><a href=\".\">Refresh Table</a></p>";
88  
89      private static String PAGE_FOOTER = "</body></html>";
90  
91      // use CDI to inject a bean that will perform JPA and JMS operations
92      @Inject
93      private XAService xaService;
94  
95      /**
96       * <p>Servlet entry point.
97       * </p>
98       * <p>The behaviour of the servlet is controlled by servlet query parameters:
99       * </p>
100      * <p>Database inserts/updates are controlled by the presence of parameters "submit" (with value "Submit") and "key".
101      * </p>
102      * <p>Database deletes are controlled by the presence of parameters "submit" (with value "Delete") and "key".
103      * If the value of "key" is empty then all rows are deleted otherwise just the row with the key value is deleted.
104      * </p>
105      * @param req the HTTP request
106      * @param resp the HTTP response
107      * @throws ServletException
108      * @throws IOException
109      */
110     @Override
111     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
112         /*
113          * Read servlet parameters to determine which key value pair to use and
114          * whether this is an insert/update/list request or a delete request
115          * @see XAServlet#PAGE_CONTENT
116          */
117         String key = req.getParameter("key");
118         String value = req.getParameter("value");
119         boolean delete = "Delete".equals(req.getParameter("submit"));
120 
121         PrintWriter writer = resp.getWriter();
122         // perform the database operation
123         String responseText = xaService.updateKeyValueDatabase(delete, key, value);
124 
125         writer.println(PAGE_HEADER);
126         writer.println(PAGE_CONTENT);
127         writer.println(responseText);
128         writer.println(PAGE_FOOTER);
129 
130         writer.close();
131     }
132 }