[053] public platform development tutorial Article 23rd-SAE does not support XStream framework solutions,-saexstream
Problem description
In the last few days (after December August 20, 2014), many netizens suddenly responded that the public platform development code in Liu Feng's blog reported an error on SAES, or the code could be deployed normally, but the message sent to the public account did not respond. In the past, some beginners have questioned whether the code in my blog can run normally. I finally proved that it was caused by their incomprehension and carelessness, but this time, many people responded to the same problem in just a few days, which caused me enough attention. For the problem that "the same code can run normally before, but cannot run now", I guess it may be a change in the running environment, this should be due to the recent updates made by SAE.
Problem Analysis
If log4j or slf4j is used in a Java Web project and logs are output to the console, after the project is deployed to SAE, you can view application logs in the "log center" of the SAE website. View the HTTP service error logs and view the error logs as shown in:
For ease of viewing and explanation, I formatted the preceding error log. The result is as follows:
101.226.62.83 [27/Aug/2014:17:23:10 +0800] JAVA_SAE_Fatal_error: Error for /coreServletjava.lang.NoClassDefFoundError: Could not initialize class org.liufeng.weixin.util.MessageUtilat org.liufeng.gywodejia.service.CoreService.processRequest(CoreService.java:40)at org.liufeng.gywodejia.servlet.CoreServlet.doPost(CoreServlet.java:54)at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:538)at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)at com.sina.sae.servlet.SaeServletHandler.doHandle(SaeServletHandler.java:49)at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:517)at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:225)at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:937)at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:871)at com.sina.sae.webapp.SaeWebAppContext.doScope(SaeWebAppContext.java:166)at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:259)at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)at com.sina.sae.handler.SaeUserInfoHandler.handle(SaeUserInfoHandler.java:105)at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:305)at org.eclipse.jetty.server.handler.HandlerW yq36.javaruntime
The second line in the log shows that a NoClassDefFoundError error (the class cannot be found) is reported during access to/coreServlet, And the org. liufeng. weixin. util. MessageUtil class cannot be instantiated. In the deployed WAR, MessageUtil. class exists clearly. Why cannot I find the class? Let's take a look at what MessageUtil. java has written. The source code is as follows:
Package org. liufeng. course. util; import java. io. inputStream; import java. io. writer; import java. util. hashMap; import java. util. list; import java. util. map; import javax. servlet. http. httpServletRequest; import org. dom4j. document; import org. dom4j. element; import org. dom4j. io. SAXReader; import org. liufeng. course. message. resp. article; import org. liufeng. course. message. resp. musicMessage; import org. liufeng. course. m Essage. resp. newsMessage; import org. liufeng. course. message. resp. textMessage; import com. thoughtworks. xstream. XStream; import com. thoughtworks. xstream. core. util. quickWriter; import com. thoughtworks. xstream. io. hierarchicalStreamWriter; import com. thoughtworks. xstream. io. xml. prettyPrintWriter; import com. thoughtworks. xstream. io. xml. xppDriver;/*** message tool class ** @ author liufeng * @ date 2013-05-19 */public class MessageUtil {/*** return Message Type: text */public static final String RESP_MESSAGE_TYPE_TEXT = "text";/*** return Message Type: music */public static final String RESP_MESSAGE_TYPE_MUSIC = "music";/*** return Message Type: image text */public static final String RESP_MESSAGE_TYPE_NEWS = "news "; /*** Request Message Type: text */public static final String REQ_MESSAGE_TYPE_TEXT = "text";/*** Request Message Type: image */public static final String REQ_MESSAGE_TYPE_IMAGE = "image" ;/*** Request Message Type: link */public static final String REQ_MESSAGE_TYPE_LINK = "link";/*** Request Message Type: geographic location */public static final String REQ_MESSAGE_TYPE_LOCATION = "location";/*** Request Message Type: audio */public static final String REQ_MESSAGE_TYPE_VOICE = "voice "; /*** Request Message Type: Push */public static final String REQ_MESSAGE_TYPE_EVENT = "event";/*** event type: subscribe) */public static final String EVENT_TYPE_SUBSCRIBE = "sub Scribe ";/*** event type: unsubscribe (unsubscribe) */public static final String EVENT_TYPE_UNSUBSCRIBE =" unsubscribe ";/*** event type: CLICK (custom menu CLICK Event) */public static final String EVENT_TYPE_CLICK = "CLICK";/*** parse the request (XML) ** @ param request * @ return * @ throws Exception */@ SuppressWarnings ("unchecked") public static Map <String, String> parseXml (HttpServletRequest request) throws Exception {// store the parsing result in the HashMap Map <String, String> map = new HashMap <String, String> (); // obtain the InputStream inputStream = request from the request. getInputStream (); // read the input stream SAXReader reader = new SAXReader (); Document document Document = reader. read (inputStream); // get the xml root Element root = document. getRootElement (); // obtain the List of all child nodes of the root Element <Element> elementList = root. elements (); // traverse all subnodes for (Element e: elementList) map. put (e. getName (), e. getText (); // release resource I NputStream. close (); inputStream = null; return map ;} /*** convert a text message object to xml *** @ param textMessage the text message object * @ return xml */public static String textMessageToXml (TextMessage textMessage) {xstream. alias ("xml", textMessage. getClass (); return xstream. toXML (textMessage);}/*** convert music message object to xml ** @ param musicMessage music message object * @ return xml */public static String musicMessageToXml (MusicMessage musicMessage) {xstream. Alias ("xml", musicMessage. getClass (); return xstream. toXML (musicMessage);}/*** convert a text message object to xml ** @ param newsMessage text message object * @ return xml */public static String newsMessageToXml (NewsMessage newsMessage) {xstream. alias ("xml", newsMessage. getClass (); xstream. alias ("item", new Article (). getClass (); return xstream. toXML (newsMessage);}/*** extends xstream to support CDATA blocks ** @ date 2013-05-19 */private static XStr Xeam stream = new xstream (new XppDriver () {public HierarchicalStreamWriter createWriter (Writer out) {return new PrettyPrintWriter (out) {// Add the CDATA mark boolean cdata = true for all xml node conversions; @ SuppressWarnings ("unchecked") public void startNode (String name, Class clazz) {super. startNode (name, clazz);} protected void writeText (QuickWriter writer, String text) {if (cdata) {writer. write ("<! [CDATA ["); writer. write (text); writer. write ("]>");} else {writer. write (text );}}};}});}
MessageUtil is a message processing tool class. The code of this class can be roughly divided into the following three parts:
1) 33rd ~ Row 91: defines several constants to indicate the Request Message Type, event type, and Response Message type.
2) Row: defines a parseXml () method to parse xml messages sent from the server using the dom4j tool.
3) 126th ~ Row 3: Use XStream to convert a Java Message object to xml.
Obviously, the problem should not appear in Part 1 of the Code, because this code is too common. I guess the problem may be related to the third-party tool dom4j or XStream referenced in Part 3 and 2nd code. Is there any update by SAE that does not support dom4j or XStream? It is not difficult to prove it. Write the simplest Java web project, and only use dom4j or XStream to know what went wrong. Fortunately, when I met an official SAES operator, I was so lazy that I directly consulted him. After asking the SAES R & D personnel for help, the answer was: sun is used in XStream source code through reflection. misc. the Unsafe class is disabled by SAE due to security reasons. This is why the NoClassDefFoundError is reported when XStream is deployed to SAE. Oh, this is the case. If you know the reason, you can always find a solution.
Problem Solving
The XStream framework is used to convert Java objects to XML objects. R & D engineers of SAE recommend that you use other frameworks with similar functions, such as Xerces, jdom, or dom4j. Of course, this is a good suggestion. If it is in a new project, I will definitely do this. But now the problem is that if we use other frameworks to replace XStream, we may need to modify not only MessageUtil a class, but this change is too big, it's hard for me to tell so many readers. For this reason, I thought about the possibility of modifying the XStream framework source code to solve the problem.
I'm on the XStream Official Website.
Many readers may want to know how this problem is solved and do not want to listen to me for a long time. It is better to teach people to fish than to teach people to fish. The reason why I wrote the whole process of discovering, analyzing, and solving problems is also to help more beginners gradually master their own solutions.
For xstream-1.3.1-sae-liufeng.jar: http://download.csdn.net/download/lyq8479/7830911.
Statement
The solution I provide is a bit violent. It aims to help you continue to test and learn about public platform development on SAE, which may affect the performance of XStream. If it is used as a formal project and runs the public platform program on a non-SAE platform, we recommend that you use the official XStream jar.
If you think blog articles are helpful to you, please leave a message or follow the public account below to support Liu Feng!
Post please indicate this article from Liu Feng blog (http://blog.csdn.net/lyq8479), please respect others' hard work results, thank you!
How to call the sae database for public platform development
Echo is printed to the screen by php instead of a reply.
Use the responseText (string str) method in the open Wechat class to reply to text messages.
For other messages, see the development documentation.
Object-oriented thinking is required for calling.
This-> responseText (string str );
The preceding method is only applicable to php, C #, Java, or other documents that need to be queried separately.
Which of the following is better for public platforms to develop bae and sae?
I can still look at my preferences. I am using sae now. I feel like this is a good operation, and the interface can be understood at a Glance. There is no much difference in other words.