Yesterday I tried using Tomcat and Servlets for the first time (I come from IIS/C#/MVC).
I'm also using AngularJS and Guice.
I've made a Servlet that has a single method:
#Singleton
#SuppressWarnings("serial")
public class CommandServlet extends HttpServlet {
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println(req.getParameterMap());
}
}
I've made a service in Angular that looks like the following:
app.factory('console', [ '$http', function($http) {
var console = {};
console.execute = function(gameId, command) {
$http.post("Command/", {
gameId : gameId,
command : command
}).success(function(data, status, headers, config) {
}).error(function(data, status, headers, config) {
});
};
return console;
} ]);
In my controller I inject the service and expose it to the view via an "execute" function on the scope:
app.controller('PlayController', function($scope, console) {
$scope.consoleIn = "";
$scope.gameId = 1;
$scope.execute = function(command) {
$scope.consoleOut = console.execute($scope.gameId, command);
};
});
And in my view I have a button which calls the function and passes in text from an input element:
<input ng-model="consoleIn" type="text">
<button class="btn" type="button" ng-click="execute(consoleIn)">Go!</button>
For some reason the console on my Tomcat server is printing an empty Map ({}) without the parameters being passed with the POST request. When I look at the network tab in Chrome's Console thingy and see that the parameters are being sent ({"gameId":1,"command":"a"}), so my question is 1) Am I doing the right thing to get the values out of the POST request (getParameterMap() ?) and 2) if I am doing the right thing, what am I doing wrong so that the request my browser makes isn't getting to my servlet properly?
EDIT:
I ended up using Jersey as my container (I think it's called) instead of Java's default Servlets. I did this after seeing Jersey popping up with Guice often on Google, thinking there would be sufficient documentation to get the two of them working together. There are several examples and I sort of drew on several, especially this one.
The snag I ran into getting it to work was this, but now everything's good to go.
Overall I'd say that if you like Guice for your DI and want to make a Java website, Jersey is good. It appears to be for a different more specialized functionality of RESTful services than regular servlets - but that's what I needed, anyway. From my un-scientific Googling observations besides Tomcat there's Grizzly and Jetty that are popular as well - you may want to look into them if you're having trouble with Tomcat.
I hope this edit saves someone the hours I spent yesterday and today getting it to work.
What does it actually print? Some of the Tomcat Map implementations don't print their contents in their toString() method. Try another way of seeing what's in it. You'll find its all there.
Related
I need to make a Servlet which will manage some information and, after that, will go to a Liferay 6.2 Portlet. Both in the same server.
I need the Servlet to send a parameter, but I don't want to send it GET, but POST method. So, I try to put it in the session to retrieve it from the Portlet.
At the Servlet, I have:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.getSession().setAttribute("param1", "TEST 1");
url = "http://myServer/";
response.sendRedirect(response.encodeRedirectURL(url));
} catch (Exception e) {
e.printStackTrace();
}
}
And at the Portlet I manage the information at render method, as I want to get param1 before I render the page:
public void render (RenderRequest renderRequest, RenderResponse renderResponse)
throws PortletException, IOException {
super.render(renderRequest, renderResponse);
//Try to retrieve from getOriginalServletRequest
HttpServletRequest servletReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
String param1 = servletReq.getSession().getAttribute("param1").toString();
//Try to retrieve from getHttpServletRequest
HttpServletRequest servletReq_ = PortalUtil.getHttpServletRequest(renderRequest);
String param1_ = servletReq_.getSession().getAttribute("param1").toString();
}
As you can see, I tried to retrieve from getHttpServletRequest and from getOriginalServletRequest, but I always get the param1 null.
Any suggestion?
Thank you in advance!
Update question:
I'm being called from a third part, and I'm receiving a GET parameter I want to evaluate.
After that, and not rendering a page in the middle, I want to redirect to one or another Portlet, depending of that evaluation.
I need to send some personal information to those Portlets, so I want to send some parameters in POST method.
A Servlet doesn't fit as doesn't share session with Portlets.
I've tried to implement a landing Portlet, but the redirect can only be done in action phase, so I'd need to render a (empty) page before the redirect, don't like that part. Render phase doesn't allow redirect (even getting PortalUtil.getHttpServletResponse(), doesn't work)
Any suggestion? Thanks!
A servlet and a portlet will not share the same session. The portlet is living within the portal server, e.g. Liferay. The servlet is typically in its own web application, thus completely separated by design.
If you need to communicate between the two, here are two possible solutions/workarounds:
reimplement your servlet as a portlet, potentially utilizing the resource-phase of a portlet
use a request parameter instead of a session attribute
Edit after all of the comments:
It seems best to take a step back and look at the underlying problem - what is the problem that you're actually trying to solve? The content of your question is how you're trying to solve it, and obviously there are challenges. It looks like the problem needs a different solution in the first place.
My answer describes why your solution can't work, but that obviously doesn't help solving the underlying problem.
I am trying to develop a RESTful app with Spring. The REST service must be parametrized in a database, I mean, a generic Service that can change the whole URL from a database info doing the same work but pointing to differents URL directions.
I was searching for info related for ages. Does anyone know about useful tutorial?
is it possible to do?
Thanks everyone!
You're better off creating a simple Servlet that will listen to a static root url and respond dynamically according to the database value.
public class Config {
public static String restPath = "valueReadFromDB";
}
#WebServlet("/appName")
public class AppServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
if (req.getURI().contains(Config.restPath) {
// add your logic
}
}
}
You can call this like so: http://your.host.name/appName/dynamicUrlReadFromDB
Don't blindly attempt to use Spring just because it is cool or fashionable. Sticking to the basics can always yield excellent results and allows for fine-grained control of your application something that Spring cannot always do.
The api is tagged:
#Api(version = "v1",
description = "API for interfacing with accounts",
defaultVersion = AnnotationBoolean.TRUE)
and one of the methods I want to call is:
#ApiMethod(name = "account.register",
path = "account",
httpMethod = HttpMethod.POST)
public void register(HttpServletRequest request, HttpServletResponse response)
{ ...
but I can't seem to figure out the url to access it :(
I tried POST-ing to myapp.appspot.com/_ah/api/myapi/v1/account but it 404's
A few things...
I think one doesn't usually use Endpoints this way: by posting manually to a URL. Instead, you are expected to generate a client library (which encapsulates the URL) and then use the client library.
If you just want to check out your endpoints, I've heard that the API explorer is very useful. For your specific application you'd use:
https://myapp.appspot.com/_ah/api/explorer
and be redirected to a version of the APIs Explorer for your application.
The actual calls to your App Engine backend are to paths such as this: /_ah/spi/MyEndpoint.myMethod. (Note: the spi versus api in the path.) The actual path you tried to construct is Google's API serving infrastructure acting as a frontend to your application.
You do not have any (HttpServletRequest request, HttpServletResponse response) in an endpoint.
The easiest thing to do is to make your java class (which you want to persist) and then in eclipse point at the java class and right click and select "google -> generate google cloud endpoint class" Then you get a good idea how it looks in different scenarios.
If you want to send parameters you have to add for instance myMethod( #Named( "myName" ) String name ).
But check out the endpoint genration first, it makes it all much simpler
And look here for more info: https://developers.google.com/appengine/docs/java/endpoints/annotations
Right now based on the site name in the URL parameter, we decide the appropriate actions to take(method calls etc) in the Java (Standard Jsp/Servlet web applications). For example, the request would be something like www.oursite.com?site=Ohio
Wondering what would be the alternative of doing this without having to provide URL parameter.
You could use POST instead of GET.
GET appends request parameters to the end of the URL.
POST sends encoded data using a form.
http://www.tutorialspoint.com/jsp/jsp_form_processing.htm
Why not just code it into the path?
www.oursite.com/Ohio
If you're just using straight servlet api, you can just do something of this nature:
String path = request.getPathInfo();
String site = path.split("/")[0];
That being said, most web frameworks have some support for helping with this.
For example, in spring mvc:
#RequestMapping(value="/{site}/blah/blah", method=RequestMethod.GET)
public ModelAndView blahBlah(HttpServletRequest req,
HttpServletResponse resp,
#PathVariable("site") String site) {
// do stuff here
}
Of course you could do this at the controller level too if all your methods need that sort of mapping:
#Controller
#RequestMapping(value="/{site}")
public class MyController {
#RequestMapping(value="/blah/blah", method=RequestMethod.GET)
public ModelAndView blahBlah(HttpServletRequest req,
HttpServletResponse resp,
#PathVariable("site") String site) {
// do stuff here
}
}
I believe this is cleaner than a query param, though it still shows up in your URL. There's other, more complex methods like using apache's reverse proxying and virtual host capabilities to switch based on site names. You could do something at login, and store the site in session. It all depends on your requirements.
You could use an alternate URL, like ohio.oursite.com. This process could be automated by having your server respond to *.oursite.com. I would probably set up a filter that looked at what the subdomain was and compared that with a predefined list of allowed sites. If it didn't exist, you could redirect back to the main (www) site. If it did, you could set a request attribute that you could use in a similar way that you currently use the request parameter now.
I've a third-party servlet inside a JAR that I cannot change. I've extended that servlet and been using it normally as a servlet should be used, the client side makes an HTTP request that invokes my servlet.
But now the client wants an automatic service, that is, I will need to do some requests to that third party servlet from the same webapp where the servlet is.
I looked at the the third party servlet code but I didn't found a place to bypass the servlet because the HttpServletRequest and HttpServletResponse objects are passed from method to method... Basically it seems that I would need to re-implement all the third party code.
Solutions I found but do not satisfy me:
Call servlet from URL with HttpURLConnection: My common sense says that calling the third party servlet from a url is not the best way to
go, besides the overhead added, I don't want to expose the third party
servlet. Calling my servlet from a url also brings problems with
sessions and other things.
Call the doGet directly: This seems to be out of the question because there is no implementation for the HttpServletRequest and
HttpServletResponse.
Use jMock or something like that: Didn't explore this solution yet, but it seams wrong to use a test-driven library in the real
environment.
Anyone has an idea how to interact with that third party servlet?
EDIT:
Since my English is not very good and I'm finding difficult to explain myself here goes a schematic to try to explain better
EDIT2: After a meeting the third party maker they offer to isolate the methods I need to avoid calling the servlet. If you don't have the same luck I did check out both gigadot and BalusC answers.
If I understand your question correctly, you have implemented or have a third party servlet that generate the report for you.
Now what you want to do is to periodically generate the report and store in session so that when user want to get the report they can retrieve it using another servlet.
If this is the case then you want the task to be running periodically on your server. You will need some sort of task scheduler to run on your server and what the task does is just make a http request to your servlet (this can be http GET or POST).
Calling my servlet from a url also brings problems with sessions and other things.
If that's the sole problem, then just use the CookieManager to maintain the cookies (and thus also the session) in subsequent URLConnection calls.
// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
You could try to separate out your servlet logic into several phases. The entry point that takes the request/result, the action that processes parameters sent and generates the output.
public void doGet(HttpServletRequest req, HttpServletResponse rsp){
relay(rsp,act(req.getParameter("a"));
}
public static String act(String a){
return "You provided: " + a;
}
public static void relay(HttpServletResponse rsp, String content){
rsp.setResponseCode(200);
rsp.getOutputStream().write(content.getBytes());
}
This lets you call act(whatever) to do what you want, and then do what you want with the response. If returning a string is not enough, you could make any return type you want, probably something that could contain a list of headers, response code, and content template.