I am trying to make an API with Jetty Server, and I have this simple GET request:
#GET
public String helloWorld(){
return "Hello world";
}
In order to make a POST request, I assume that one must save the input to the Jetty server. I have tried to research for quite a while, but found nothing.
I imagine something like this:
#POST
public void Save(String stringToSave) {
// Save to DB?
}
You could likely google this but let me give you a quick overview. A Servlet is a chunk of code that is normally run during an HTTP action - GET, POST, etc. It is the original technology of the JavaEE world, having been released in the late 1990's.
A simple Java servlet, using modern annotations, would look something like:
#WebServlet(name = "SampleServlet", urlPatterns = "/sampleServlet")
public class SampleServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP POST is sent
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP GET is sent
}
}
The important parts to note are that the class extends HttpServlet and that you have to write code to pull data out of the request and push it into the response. This isn't bad to do but it does have to be done.
JAX-RS is a newer standard, aimed simplifying the creation of REST services. It too is a chunk of code that runs during an HTTP interaction.
A simple example of this would be:
#Path("/sampleService")
public class SampleService{
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#POST
#Path("/v1/hello")
public Response sayHello( SomeObject someobject ) {
The code here is both simpler and a bit more complex. The use of annotations helps determine the path that the service exists on a URL (in this case /sampleService/v1/hello), the HTTP method, and the Content-Type for both the request and response. Additionally, if the SomeObject object is defined correctly, the JAX-RS framework will automatically deserialize the incoming JSON or XML payload into an object for you.
The Response object contains the HTTP response code (perhaps a teapot) and a response body. In this example, the body will be automatically serialized back to the requestor in a way that matches the Accept header of the HTTP request (i.e., JSON for an application/json Accept header and XML for application/xml).
Note that while not directly related the JAX-RS framework takes advantage of the Servlet framework. Indeed in JAX-RS you can access the HttpServletRequest and HttpServletResponse object in your methods.
Which way is "better"? In general I would recommend using JAX-RS where possible as it is the newer standard and is a bit easier to implement. However, if you do any work in the JavaEE world you're very likely to run into Servlet code so it's important to understand it too.
Note that both Servlets and JAX-RS require an application server of some sort. Jetty is one of those. Another very common one is Tomcat. The application server sets up the environment for your code and listens for incoming HTTP messages. When it gets one it looks to see if it knows how to handle the URL and routes to the appropriate place. In the servlet world the server routes solely on the URL. In the JAX-RS world the server routes on the URL and, if specified by the #Consumes annotation, the HTTP Content-Type header too.
There is much more but let's start there and see if it answers what you're after.
I'm new to Java server-side programming, my question is basically to get to a starting point using Servlets (low level without using spring mvc etc.) and then build my way up from there, coming from node.js background where a route definition would start with a function (app.get(request, response) {}, app.post(request, response) {} etc.), and the function would receive request and response in parameters for one of http methods (GET, POST, PUT, DELETE).
If someone can please help on the starting point of how do I define methods against a route (let's say /users) inside a servlet class that'd map to http methods while providing request and response in it's parameters.
My attempt
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException , IOException {
}
I believe what you want are Servlet mappings. You can also find a bit more info here
But basically this is the way you tell the webserver (e.g. Tomcat) what servlet to use to answer requests sent to a given url pattern. Thus you map the pattern with the servlet you want to use to serve it.
You can also find more info on the inner workings here.
Edit: If you want to handle all verbs you can use a service. From the first link:
You may have seen other servlet examples implement the doPost() and/or doGet() methods. These methods reply only to POST or GET requests; if you want to handle all request types from a single method, your servlet can simply implement the service() method. (However, if you choose to implement the service() method, you cannot implement the doPost() or doGet() methods, unless you call super.service() at the beginning of the service() method.) The HTTP servlet specification describes other methods used to handle other request types, but all of these methods are collectively referred to as service methods.
All the service methods take the same parameter arguments. An
HttpServletRequest provides information about the request, and your
servlet uses an HttpServletResponse to reply to the HTTP client. The
service method looks like the following:
public void service(HttpServletRequest req,
HttpServletResponse res) throws IOException { ... }
I have 2 java classes and I want to transfer data between them.
I take user id as parameter in a previous jsp form, and in a java class, using setAttribute I create a atribute named st_id.
then in another java clas I want to retrieve this data, but I get null.pointer exception.
first java file;
public class Signin implements Action {
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
Student stu = new StDAO().getUser(request.getParameter("st_id").toString());
request.setAttribute("st_id", request.getParameter("st_id").toString());
...
second;
public class addCourseStu implements Action{
#Override
public String process(HttpServletRequest request, HttpServletResponse response) throws Exception {
TakeCourseDAO pf = new TakeCourseDAO();
String s= (String) request.getAttribute("st_id");
So s is null, it's not my intention.
A request exists from the time the web browser sends it to the web server until the web server (via the servlet) has made its response.Every request for a servlet has its own accessibilty scope. From a servlet, you can:
add new attributes to the request's scope
obtain exisiting attributes from the request's scope
remove exisiting attributes from the request's scope
As you are getting null it is quite obvious that the attribute is not accessed within the scope.
You can try alternatives like Session scope or Application scopes which ever suits you
It is not entirely clear what you want to do but I gather that you want to maintain some state on the server between two requests right?
Look into sessions & cookies for this.
What you do here is weird as it seems you are setting an attribute on an incoming request in the first file.
I have a HashMap of custom objects being passed to a JSP using RequestDispatcher and I am able to access the object and its properties using JSTL.
However the code fails in case the parameter is sent using response.sendRedirect() .
I am not sure what the reason is and how to make it work?
The response.sendRedirect() basically instructs the client (the webbrowser) to send a new request on the given URL. You'll also see this being reflected by a change in the browser address bar.
A new request does of course not contain the attribtues of the previous (or any other) request. That would otherwise have broken the whole concept of "request scope".
To preprocess a GET request, you need to do the job in doGet() method of a servlet and then redirect to the URL of that servlet instead.
E.g.
response.sendRedirect(request.getContextPath() + "/foo");
and
#WebServlet("/foo")
public class FooServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, Foo> foos = fooService.map();
request.setAttribute("foos", foos);
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
}
}
Note that this problem is in no way related to having a hashmap of custom objects in the request scope.
See also:
Our servlets wiki page
You can not share a request attribute in response.sendRedirect as it creates a new request.
But, if you want that HashMap, in response.sendRedirect, you can put that in session like
request.getSession().setAttribute("myMap", [HashMap object]);
and can share between the servlet and JSP. This works in both RequestDispatcher and sendRedirect.
I have a general question about using Servlet and JDBC.
For instance, I have a class called MyDatabaseManager, which provides functions
public boolean updateUser(User user) {...}
public boolean deleteUser(User user) {...}
public boolean inserUser(User user){...}
, these functions will access and manipulate the Database.
My question is on the Servlet implementation. I am using three Servlets (UpdateUserServlet,InsertUserServlet and DeleteUserServlet) at the moment and each Servlet calls the MyDatabaseManager instance (only one instance here, using Singleton pattern) function. (For example, UpdateUserServlet calls MyDatabaseManager.updateUser ...).
I think this is the most straightforward way of using Servlet and Database. But I am not sure if this is the correct way of doing it. For example, how is this implemented in the industry world.
People don't really use servlets directly nowadays, they use frameworks that allow you to simplify your work, but if you really want to use servlets, you can make all actions in a single one, using the other methods, doPut, doDelete and even creating your own methods. Here's a sample of how you would do it:
public abstract class BaseServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String method = request.getParameter("_method");
if ("form".equals(method)) {
this.doForm(request, response);
} else {
if ("delete".equals(method)) {
this.doDelete(request, response);
} else {
super.service(request, response);
}
}
}
protected void doForm(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
throw new UnsupportedOperationException();
}
}
As you can see, this Servlet uses a special field _method on forms to decide what special method to call, if the _method is not available it's going to use the usual service method and is going to call doGet or doPost.
And here's how an implementation for this servlet would look like:
public class UsersServlet extends BaseServlet {
private UsersRepository cadastro = new UsersRepository();
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("usuarios", cadastro.list());
req.getRequestDispatcher("/usuarios/listar.jsp").forward(req, resp);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
User usuario = this.getUser(req);
usuario.setNome(req.getParameter("nome"));
usuario.setEmail(req.getParameter("email"));
usuario.setSenha(req.getParameter("senha"));
this.cadastro.persist(usuario);
resp.sendRedirect(req.getContextPath() + "/usuarios");
}
protected User getUser(HttpServletRequest req) {
User usuario;
if (req.getParameter("id") == null) {
usuario = new Usuario();
} else {
Long id = new Long(req.getParameter("id"));
usuario = this.cadastro.search(id);
}
return usuario;
}
#Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
User usuario = this.getUser(req);
this.cadastro.remover(usuario);
resp.sendRedirect(req.getContextPath() + "/usuarios");
}
#Override
protected void doForm(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
User usuario = this.getUser(request);
request.setAttribute("usuario", usuario);
request.getRequestDispatcher("/usuarios/form.jsp").forward(request,
response);
}
}
This way you can make it all in a single servlet.
Difficult to answer because there are hundreds of design patterns out there! I know a good one about Database management is called DAO (data access objects). I use this one a lot. I advice you to take a look.
Don't get me wrong, a Singleton to hold your Manager is a good idea. Pretty much that's what I usually do too. However, usually I have a DAOFactorySingleton which pretty much have the responsibility to generate all classes DAO in my app and this factory is good because I can have some DataSource rules that this factory just poll from somewhere and inject in my DAO! So, pretty much, each DAO doesn't have to care about things like JDBC connection!
Follow 2 links to explain more about DAO!
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
http://community.jboss.org/wiki/GenericDataAccessObjects
The second one is to use with hibernate! you can read it and is not mandatory using just with hibernate. I really like that second one, more complex though.
This is surely a matter of design choice, you can adopt a framework like Spring, Struts etc.. which make this much easier. Alternatively if you want to use the classic servlet request/response pattern, I will suggest creating a parent servlet which intercepts request and passes it on to the right method to perform the request.
Additionally you have a choice to various ORM solutions like Hibernate, JPA etc.. which you can use to handle your database access operations. Yet if you choose to stick to the classic JDBC calls, you can use Filters and Handlers to decide which calls to provide wrap database connection and operation against.
Singleton on the Database class sounds good, especially as it seems to contain update/delete/insert code.
If you're using Connection Pools, make sure you Singleton the DataSourceFactory.
Many in the industry use ORM + Dependency Injection framework + transaction manager + database pooling libraries, for example Hibernate (ORM) + Spring DI (Dependency Injection) + Spring transaction manager (transaction manager) + Apache DBCP (DB connection pooling).
Sometimes when the use of ORM cannot be justified (e.g. very simple DB schema, ORM performance overhead is prohibitive due to the nature of the app. etc.), developers might use raw JDBC. Many would still use dependency injection and DB connection pooling.
It is very rare that the use of dependency injection or DB connection pooling cannot be justified. I.e., unless it is a very rare, special app., developers in the industry do use dependency injection framework and DB connection pooling.
In this case the state that needs to be managed is managed by the DB connection pooling framework, so you should not have to worry about state management or thread safety (as long as you don't share anything between different threads yourself and follow the API of the DB connection pool framework). I.e., you won't need a singleton. If you implement your own DB connection pool, then using a singleton would make sense.
If a developer doesn't want to use any framework (e.g. creating a very simple tool), then many would just open a connection every time (for each thread). In this case, you again don't need to manage any state so you won't need a singleton.
In the industry world, we are all for simplicity. For example, for user interaction from browser, to server, to a persistence storage (database), we follow these approaches.
An MVC pattern, first and foremost. This would allow us to totally not write a Servlet for each user interaction from browser to server. What this allows us to do is to do the following:
Allow the controller to handle user request and link it to our user action (our model). This model allows us to write business logic to respond to user data.
In today's Java World, Frameworks exists that meets our MVC requirements. The one that comes out the Java box is JSF (JavaServer Faces).
For backend, we definitely use databases, but we are clever too and use ORM (Object Relational Mapping) to model our real-world problem into an Object model and how to best persist (store) these object models. Some usesERM (Entity-Relational Modelling) to design a semantic data model.
In the middle, the business logic, we add a service (as the business logic layer) doesn't want to care about where to read/write data, as long as they can see the data it wants. For this, a Service layer is added that facilitates this. In essence we have this effect.
public class ActionServlet extends HttpServlet {
//Action registration
public void init() {
ActionMapping mapping = .....; //some instatiation
mapping.setAction("/userRegistration", UserRegistrationAction.class);
//Save it in Application Scope
getServletContext().setAttribute("actionConfig", mapping);
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = request.getPathInfo();
Action action = ((ActionMapping)getServletContext().getAttribute("actionConfig")).getAction(path);
if (action == null) {
throw new Exception("No action of '" + path + "' found.");
}
action.execute(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
doAction(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
doAction(request, response);
}
}
public abstract class Action {
public abstract void execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
protected void dispatch(HttpServletRequest request, String path) {
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request, response);
}
}
public class UserRegistrationAction extends Action {
public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
//Business Logic goes here...
//Call DAO,
UserRegistrationDAO dao = ; //Some DAO instantation
User user = createUserFromForm(request);
dao.save(user);
dispatch(request, "success");
}
}
As for persistence, Java 5 & higher comes with JPA. You can use any form of ORM that you want, depending on your project scope. There's Hibernate (which also supports JPA) or if you want to, write your own DAO.
One more thing, all these processes are tedious to glue together. Fortunately, we have frameworks that helps us make our beautiful example above much easier. Frameworks like JBoss Seam does this and it fully uses Java specifications. For now, go for the simple design models and MVC (for learning purposes). As you get accustomed to the architecture, use frameworks.