I have to make a Java webapp that would listen for incoming HTTP POST requests, then retrieve the XML contained in the request body in order to process it.
I am using Maven 4, Hibernate 3 and XML-RPC server. I successfully imported XML-RPC jar files using Maven.
Though everyone seem to say XML-RPC is the simpliest thing on earth, I am having a hard time implementing it. I am quite new to webapps.
Looking at Apache XML-RPC tutorial I understand I need to create a class such as:
public class MyServer extends XmlRpcServlet {
private XmlRpcServer server = new XmlRpcServer();
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
server.addHandler("myProcess", new MyProcessHandler);
byte[] result = server.execute (request.getInputStream());
response.setContentType ("text/xml");
response.setContentLength (result.length());
OutputStream out = response.getOutputStream();
out.write (result);
out.flush ();
}
}
But that won't compile because the "execute" method expects a XmlRpcRequest parameter. Any hint about what I am doing wrong?
Aside from that, I don't understand how I am going to get the request's body from my function myProcess(). I have a MyProcessHandler class (which extends no class) implementing a myProcess() function. Do I need to add a parameter in this function? Is so then which type would it be?
The main problem lies in the XML-RPC version: Apache first made an old version named helma-xmlrpc, then refactored it with deep changes into org.apache.xmlrpc. Though Apache updated some parts of its XML-RPC online documentation, some other parts still reference helma-xmlrpc with no hint, on each page, of the version used.
Moreover, Apache says that projects using helma-xmlrpc only have to update their imports in order to use the new version org.apache.xmlrpc, no impacts on the code - That's totally wrong. Some methods and even some classes disappeared, or the signature changed, and some classes have been put into sub-directories, so the imports don't work anymore.
Okay. So once I figured out that, I also understood that most of the Internet tutorials dealing with Apache XML-RPC use the old helma-xmlrpc version, but show their imports as org.apache.xmlrpc. As a result, the implementations they present won't work if you paste it in your own project which uses org.apache.xmlrpc. It doesn't even compile.
I looked over the Internet for up-to-date org.apache.xmlrpc-implementation-with-servlets tutorials with no result. Hence I decided to use old helma-xmlrpc and all went well. With Helma, the code I posted in my first message now compiles and is right.
As for the link between the listener and MyProcessHandler class, it exists thanks to the addHandler function. Once the handler is declared, all incoming requests with methodName like 'myProcess.myFunction' are automatically redirected toward MyProcessHandler.myFunction() when the instruction server.execute(...) is processed.
For that to work, myFunction() must declare one String input parameter. When myFunction() will be called, this parameter contains the body of the request (extracted by request.getInputStream() in the servlet). myFunction() also has to return something, which will be returned into the byte[] result variable of the servlet.
I made good use of the link below, very complete and treating of helma-xmlrpc only with no pretense of using org.apache.xmlrpc...: http://www.perfectxml.com/oreilly/chapter.asp?row_id=11
I hope this answer is clear enough (my English speaking is not perfect...) and it will help other developers to understand Apache XML-RPC.
You can use XmlRpcServletServer (apache xml-rpc 3.1.3):
public class EmbeddedXmlRpc extends HttpServlet
{
...
protected XmlRpcServletServer server = new XmlRpcServletServer();
...
server.setHandlerMapping(phm);
...
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
server.execute(request, response);
}
}
Related
I'm in the middle of upgrading a bunch of test harness Groovy(Java) to execute against the Jersey 2.x Client (javax.ws.rs.client.Client), upgrading it from 1.x. I'll likely stumble upon the feature soon but can't see if for the changes I'm making right now. Have been poring through the API looking for an answer to my question.
The new API seems to only permit strict fluent interface verbs e.g.
Response response = invocationBuilder.get();
The old 1.x code allowed a parameter that defines the method type using a string parameter called method:
def response = userServiceContext.target()
.path("/$path")
.method(method, ClientResponse.class)
Annoyingly strict new code displaying a 'put' call (examples):
WebTarget resourceTarget = jerseyClient().target("/$path")
Invocation invocation = resourceTarget.request(MediaType.APPLICATION_ATOM_XML)
.accept(MediaType.APPLICATION_ATOM_XML)
.put(ClientResponse.class, entry)
return invocation.submit()
For convenience sake [asking too much? :) ] could someone point me to an out of the box method that does the same thing in 2.x? I've been digging around the API and I'm finding this an annoying pebble. Bonus points if you explain why that flexibility doesn't exist in the new API (without sass). Apologies in advance to questions like what have you done or why don't you try it and see!??
It looks like you can do something like resourceTarget.request().build(method)... to do what you are looking for. Check out the docs for the build(String method) and build(String method, Entity<?> entity) methods here.
The gettext-tutorial states that
The preferable way to create an I18n object is through the I18nFactory. The factory caches the I18n object internally using the the package name of the provided class object and registers it with I18nManager. Thus all classes of the same package will use the same I18n instance.
But running inside an HttpServlet (actually an VelocityViewServlet in my particular case) it seems to me that if I change the locale on the cached object it could stay like that for subsequent requests and that is not desirable because each request must be served with particular locales.
So the question is, should I instead create ad-hoc i18n objects on a per-request basis, with the specific locale of that request? I think that would be a performance penalty, so should I instead create my own manager and select the appropriate instance based on the request's locale?
Any comments greatly appreciated. There doesn't seem to be much doc or examples besides the tutorial and the Javadoc.
Update: There is one thing I tried and seems to work. Instead of declaring a private static member like the tutorial says, I just call the factory method on each request, using this special version of the I18nFactory:
getI18n(java.lang.Class clazz, java.lang.String bundleName, java.util.Locale locale)
This should get a cached instance of that particular locale (or force the load on the first request for that locale), avoiding the performance penalties on subsequent requests for the same one. If anyone can confirm this make sense:
public class Foo extends VelocityViewServlet {
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
Locale reqLocale = request.getLocale();
I18n i18n = I18nFactory.getI18n(Foo.class, "app.i18n.Messages", reqLocale);
String localized = i18n.tr("Bar");
...
}
...
}
Again, I've tested this and it's working but I'd like to know if it's a correct implementation of gettext-commons for this type of application.
Thanks in advance,
--
Alejandro Imass
My service:
#POST
public String setData(#QueryParam("id") Long is, MyObject payload) {
...
}
or
#POST
public String setData(#PathParam("id") Long is, MyObject payload) {
...
}
My interceptor on the server:
Object read(MessageBodyReaderContext context) throws IOException, WebApplicationException {
Class mypayloadtype = context.getType;
InputStream mypayloadinpustream = context.getInputStream();
Long myidparam = ???????? // how to get the query or path param here?
}
EDIT: To be a bit more concrete:
What I'd like to do is to grab the XML and store it based on the parameters in a separate audit system. Maybe PreProcessInterceptor / PostProcessInterceptor are the better choices?
Any hints or alternative ways to get the param when the xml is still available for preprocessing?
Miguel
I just stumbled over the same problem today. I needed the #PathParams and #QueryParams in the read() method and ended up with something like this:
public class MyInterceptor implements PreProcessInterceptor, MessageBodyReaderInterceptor
{
private static ThreadLocal<UriInfo> uri = new ThreadLocal<UriInfo>();
public ServerResponse preProcess(HttpRequest request, ResourceMethod method)
{
uri.set(request.getUri);
...
}
public Object read(MessageBodyReaderContext context)
{
String param = uri.get().getPathParameters().getFirst("myidparam");
...
}
}
Although when thinking about it now - I'm not quite sure, if just using PreProcessInterceptor/PostProcessInterceptor will also do the trick for my (and maybe your) problem. I'll have another look tomorrow.
I am not an expert on the topic but to me it seems as if the MessageBodyReaderContext interface does not really know if it is on the server or the client side, so it cannot expose the request or its parameters / path parts etc.
So as far as I know this is not possible.
If your code knows that it lives on the server side of the rest
communication, maybe you can use a servlet filter to store the request
in a ThreadLocal and then access it from there while the request is
handled, somewhat similar to RequestContextFilter / RequestContextHolder from the spring framework? (Then the request object does not know anything about the annotations of your service, but instead one has to extract the information manually from the request. This means to have the same information in two places, so there has to be a better solution ...)
Edit: after looking at some examples I get the vague feeling that if you want to read the input stream to create an object and add path parameters to it, MessageBodyReaderInterceptor is simply not the way to go. Instead set up a MessageBodyReader which constructs the object from the request body data, and this then will be passed into the public String setData(#PathParam("id") Long is, MyObject payload), assuming that this method is annotated with a #Consumes which matches the #ConsumeMime annotation for the MessageBodyReader. There you might be able in the setData to set the missing id on the object read from the request body. Some examples related to this seem to be here: How to get full REST request body using Jersey? (but for Jersey, not jBoss :-/)
However I am not sure if that works for you, and I also feel I completely overestimated my ability to answer this question appropriately, so I hope someone more knowledgeable comes in with a better solution.
As I get more into RESTful APIs, the (good) simplicity of the approach means that you generate a LOT of boilerplate code, and code that has to match in three or four different places, e.g. for a Jersey-based stack:
HTML on the web page which provides controls (a button Create Foo)
JS on the web page which formulates the JSON and the request to create a Foo
A FooRest class method to handle the request and create a Foo
A Foo class to instantiate, which will manipulate the data structure
Are there tools which provide a starting point for some or all of this code automatically, possibly starting from something straightforward like a JSON data structure? E.g., provide:
card: {
methods: [GET],
}
handOfCards: {
methods: [GET POST PUT DELETE],
}
and at the very least end up with Ajax requests, CardRest and HandOfCardsRest classes with the specified methods stubbed out, and Card and HandOfCards classes with properties or getters/setters?
Have you tried Backbone.js? It is a JavaScript library that handles REST Ajax requests for you. It allows you to define your models to wrap the data and provides setters, getters, save and delete functions, etc.
It also allows you to bind the models to views which generate the UI HTML.
I think nearly any *rails application does all of this for you. Grails is my favorite right now, and once you get the initial setup done (a single command) you create domain classes with another command.
Once those are created, you can generate both views (html) and controllers for handling all of these actions with a single command, and the boiler plate is sufficient for a lot of initial sites. It will even create test cases for you, although you'll need to define what the actual tests do. You can program it by convention very easily, or create your own mappings from URLs -> controller actions. It has a ton of plugin support and easily handles remote submission of forms (via javascript) built in.
It doesn't take a json data structures for creation, but the domains are very easily created (using groovy) and it autowires getter/setters, service injections, etc as it is based on the Spring Framework.
Your goal should probably not be code generation of boilerplate but actually writing less code.
Spark is a Java micro web framework based on Sinatra.
Here's some example code:
import static spark.Spark.*;
import spark.*;
public class HelloWorld {
public static void main(String[] args) {
get(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Show something ..
}
});
post(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Create something ..
}
});
put(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. Update something ..
}
});
delete(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. annihilate something ..
}
});
options(new Route("/") {
#Override
public Object handle(Request request, Response response) {
// .. appease something ..
}
});
}
}
An alternate (or addition) to Juan's answer, you might want to check out Knockback.js , which takes the best of Knockout and adds the best of Backbone.js . Backbone has support for RESTful API's via it's "sync" functions. Quoting their website:
The method signature of Backbone.sync is sync(method, model,
[options])
method – the CRUD method ("create", "read", "update", or "delete")
model – the model to be saved (or collection to be read)
options – success and error callbacks, and all other jQuery request options
You might want to try a different approach altogether and try somethink like project lombok. It will at least let you nix all your getters and setters.
I have a pretty standard web app running under Tomcat 7.
What I'm now trying to do is leverage JSP/JSTL as a templating language independent of the HTTP/web serving aspects of Tomcat to produce HTML that can be emailed and converted to PDF.
Has anyone else tried to do this before and could help me with some pointers?
Thanks in advance.
In contrast to what Stephen C said, yes, JSP are Servlets, etc. etc. (And Velocity is quite good and easy to use)
But, what is a Servlet?
It's an interface. An interface with one major method:
service(ServletRequest req, ServletResponse res)
Locate the JSP class, cast it to a Servlet, create implementations of ServletRequest and ServletResponse, and then...
String jspClassName = findJspClassForJSP("your.jsp");
Class jspClass = Class.forName(jspClassName);
Servlet jspServlet = (Servlet)jspClass.newInstance();
MyServletRequest req = new MyServletRequest();
MyServletResponse resp = new MyServletResponse();
jspServlet.init();
jspServlet.service(req, resp);
jspServlet.destroy();
String results = reps.getContent();
Will this work? Well, after some work it will. Obviously you need to implement the minimum facades of the ServletRequest/Response as well as what ever your JSPs will need. But, likely you will probably need little more than the attributes and the streams. If you make your Response return a StringWriter, you're halfway there.
The next part is creating the servlet from the JSP. Handily, the Jasper compiler does that for you -- the game is invoking it. I have never done it directly, but it clearly can be done since both the servlet container does it, as well as the JSPC script/bat file, the ant task, as well as most of the Servlet containers out there use Jasper. So, that can be done. Once you know how to invoke that, you'll know the final generated class name for the JSP. (See the first line of the sample.)
Have I ever done this? No. But I bet within less than a day of messing around you'll know whether this is doable or not. I'm betting it is, especially if you don't run in to any class loader shenanigans. You'll possibly have an issue if you let your users change and regenerate a JSP (so MyEmail.jsp gets compiled in to MyEmail.class, MyEmail_2.class, etc.). But if you invoke Jasper yourself, you'll likely have more control over this.
The other hard part is determining the class name of the JSP. Most of the containers follow a basic pattern here, so if you poke around in the generated code from a WAR you'll likely find it.
Keep the JSPs reasonably simple (and an Email template shouldn't need to super complicated with embedded Java or anything making random calls), and it even more a good chance it will work.
Your solution may not be portable out of the box out of Tomcat, but you likely won't care. The folks that I've talked to that use JSP for templates, simply opened a socket to their own server and made a request. They didn't go this far either.
But on the surface, save some whacky class loader black hole hell, I bet you can get this to work pretty quick. Implement as little of the request and response as you need to, fight a few NPEs as the JSP and JSTL call stuff you weren't planning, and, as Santa says,
Hack away, Hack away, Hack away all!
Addenda:
So, for all the naysayers...
public void runJsp() {
JspC jspc = new JspC();
jspc.setUriroot("/tmp/app");
jspc.setOutputDir("/tmp/dest");
jspc.setJspFiles("newjsp.jsp");
jspc.setCompile(true);
try {
jspc.execute();
Class cls = Class.forName("org.apache.jsp.newjsp_jsp");
Servlet s = (Servlet) cls.newInstance();
MyRequest req = new MyRequest();
MyResponse resp = new MyResponse();
s.init(getServletConfig());
s.service(req, resp);
s.destroy();
System.out.println(resp.getSw().toString());
} catch (JasperException ex) {
throw new RuntimeException(ex);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (ServletException ex) {
throw new RuntimeException(ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
Amazing what source code and 1/2 hour in a debugger will do for you.
I created a simple JSP in /tmp/app/newjsp.jsp.
jspc.setUriroot tells the compiler where the base of your "web app" is located. jspc.setOutputDir tells jspc where to put the generated Java and Class files. jspc.setJspFiles tells jspc what files to compile, based off of the URI Root. jspc.setCompile told it to actually compile the code. Finally, jspc.execute() does the deed.
By default Jasper uses the package org.apache.jsp, and creates a new class based on the JSP file name. For my simple experiment, I simply put "/tmp/dest" on to the class path of my Glassfish container, so that the container would find the generated classes.
I load the class, and get an instance.
Finally, I created MyRequest, MyRequest, and, ultimately, MySession. My IDE conveniently created stubs for the respective interfaces. In this case I implemented: MyRequest.getSession(), MyResponse.setContentType(), MyResponse.setBufferSize(), and MyResponse.getWriter().
public PrintWriter getWriter() throws IOException {
if (sw == null) {
sw = new StringWriter();
pw = new PrintWriter(sw);
}
return pw;
}
Obviously sw and pw are instance variables of MyResponse.
MyRequest returned an instance of MySession. My implementation of MySession does -- nothing. But the runtime wanted a Session, it just doesn't use it on its own for my very simple JSP, and I wasn't motivated on stuffing in the the one from the Servlet.
I tested this on Glassfish v2.1. I simply added appserv_rt.jar (from glassfish/lib) to my build class path (so it could find the JspC jars), but I don't bundle it in the WAR (since it's already in the container).
And, shazam, it worked. In "real life", assuming the process that wanted to leverage the JSP was actually sourced from a web request, I would simply create an HttpServletResponseWrapper and override the earlier three methods, the rest would probably Just Work. If a web request isn't in the picture at all, then you'd need to create your own Session implementation (no big deal really, it's just a map).
I'd also use a private URLClassLoader to load the faux JSP classes. If I KNEW I'd never reload a JSP, then would just make the destination my WEB-INF/classes directory and give it it's own package and let the system load them.
But, yup, it worked. No big deal. It's just java.
This doesn't really make sense. A JSP is some nice syntax that results in the generation of a Java EE servlet class. Indeed, the "servlet" / "http" nature of a JSP is thoroughly intertwined through the APIs and the semantic model of JSPs and JSTL.
If you want to generate HTML independently of web requests, you would be better of using a different templating technology; e.g. Velocity or FreeMarker. If you then want the HTML to be delivered as web responses as well, arrange that your servlets call the templating engine to generate responses. (If you are using Spring there is existing infrastructure for this. Other frameworks may have similar support, but if not, it shouldn't be hard to implement some glue code yourself to do this.)