Spring REST service using variable URL - java

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.

Related

Swagger Java: Add custom servlet without JAXRS annotations

I have an application that is using JAX-RS (and swagger) annotations heavily and all is shown nicely in the swagger definition.
However one servlet implements a customer restful interface (oData, Apache oLingo) and this is not using any of the JAX-RS annotations. Yet I would like to document it.
To make it as simple as possible, let's say I have a class
#WebServlet("/rest1")
public class Login extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
response.setHeader("Content-Type", "application/json");
PrintWriter out = resp.getWriter();
out.print("{ \"text\": \"Hello World\" }");
}
}
I would like that servlet to show up in the swagger output as well without losing the JAX-RS entities.
According to the docs I would think I need to extend the reader to output this servlet as well and a custom ModelConverter?? to add hardcoded properties. But even if that is correct, I can't find a good starting point. Not to mention that I hope there is a simpler, more direct, way. Samples of swagger have been of no help either.

Web applications: servlet thread safety using singleton pattern

I'm looking to hopefully get into web application programming using Java, coming from a PHP/Laravel background (I have some Java experience having studied it around about 8 years ago at university).
I've been playing around for a while and feel fairly comfortable with most of the foundational concepts such as Servlets and Servlet containers as well as some popular web server/servlet container technologies used such as Jetty, Tomcat etc. I've also tried to do quite a bit of research into Java EE.
Now since I want to build up my knowledge on the subject, I don't want to use any frameworks, in fact I would like to look to build my own as a learning exercise. However, I've also looked quite a bit into some of the frameworks around, such as Spring MVC, Struts, Play and Vaadin etc.
So I've got a Maven project set up, I have a web.xml file set up pointing at a servlet that I have created and I am looking to build an entry point into my "framework".
src/main/webapp/WEB-INF/web.xml
<servlet>
<servlet-name>Application</servlet-name>
<servlet-class>com.mypackage.Application</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
src/main/java/com/mypackage/Application.java
package com.mypackage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Application extends HttpServlet {
#Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
}
}
So now I want to make my own IoC container that uses the singleton pattern (I know this is usually discouraged and is considered an anti-pattern), so it is easy to access it from other parts of my application:
src/main/java/com/mypackage/Container.java
package com.mypackage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Container {
private static Container instance;
public static Container make(HttpServletRequest request, HttpServletResponse response) {
return instance = new Container();
}
public static Container getInstance() {
if (instance == null) {
// Throw an exception
}
return instance;
}
private Container(HttpServletRequest request, HttpServletResponse response) {
// ...
}
}
I want to create a Container object for every request/response cycle (or every servlet) as the entry point to my application. So I would look to do something like this:
#Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Container container = Container.make(request, response);
// Do stuff with container and eventually respond to the client
}
Now I know that thread safety is a concern when it comes to servlets, and properties on the servlet instance are shared among threads, but my question relates specifically to the Container object I'm creating using the singleton pattern and thread safety.
Is my current approach considered to be thread safe? If not, why, and how can I make it thread safe? Bear in mind that don't actually want my Container instance to be shared among each thread and would like a separate container for each incoming request/response.
Would it be thread safe (or a recommended approach) to create a new object inside the service method of the servlet class and then have that new object create an instance of the Container? e.g.
public class Something {
public Something(HttpServletRequest request, HttpServletResponse response) {
Container.make(request, response);
}
}
#Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Something something = new Something(request, response);
// Do stuff with container and eventually respond to the client
}
Finally, would I be correct in assuming that the issue of thread safety arises due to the servlet container re-using servlet instances? As per the Java EE documentation:
The life cycle of a servlet is controlled by the container in which the servlet has been deployed. When a request is mapped to a servlet, the container performs the following steps.
If an instance of the servlet does not exist, the web container
Loads the servlet class.
Creates an instance of the servlet class.
Initializes the servlet instance by calling the init method. Initialization is covered in Initializing a Servlet.
Creating an instance in the servlet means that it is not thread-safe as a servlet instance is reused.
A Singleton or ApplicationScoped object will only have one copy across your entire application. If you want to make sure that there is only one instance of the object then annotate the class with #ApplicationScoped:
#ApplicationScoped
public class Something {
//do stuff
}
Then in the servlet inject it:
public class SomeServlet extends HttpServlet {
#Inject
Something obj;
#Override
public void service(HttpServletRequest request, HttpServletResponse response) {
//do stuff
}
}
If instead you want the class to you are using to be unique per request then make your class RequestScoped instead. Like so:
#RequestScoped
public class Something {
//do stuff
}
For more information see the CDI tutorial at https://docs.oracle.com/javaee/6/tutorial/doc/giwhl.html. Note that this will require using an application server that has CDI i.e. Payara and not just a servlet container.

REST API for registration

We want to implement a public RESTful API integrated in our software (written in java) that might be used by various clients to build small e-commerce apps (e.g. for Android or iPhone). This API includes getting a list of products, categories, shopping cart support, etc.
We need to provide an API that will allow user registration and couple of other sensitive functions. How should we protect this API against spam and bruteforcing? In the standard product we use reCAPTCHA. Any alternative for the REST counterpart?
First, think of separation of concerns. What is the purpose of REST API?
A REST API should do offer a service to the client. Client sends a request via REST protocol, and gets a response for its request. In code, this looks something like:
#GET
public Response getClientInfo(#QueryParam("clientId") Integer clientId) {
ClientDTO clientDTO = database.getClientInfo(clientId);
return ResponseWrapper.wrap(clientDTO);
}
Now, you want your REST method doing ONLY this and nothing else. Otherwise, you would put block-bruteforce-and-spam-logic in your REST method and you would get a mess of the code that is not extensible, hard to version, etc. If you want to change your, e.g. blacklisting policy you would have to change each and every REST method, and it's bulky. If you want to check the calls before the make it to REST methods, then take a look at Filters. Every request and response pass through a chain of filters and could be check for misuse of the server.
I don't know what is your technology stack is, but I would suggest looking into these:
JBoss AS7.
DeltaSpike (enables you powerful Interceptors that will check user rights and execution rights before the execution of the REST method).
for example:
#LoggedInUser
#GET
public Response getClientInfo(...) {
...
}
This security annotation #LoggedInUser (which, by the way, you define) will give sign to an Interceptor to check this security constraint, e.g.
#Secures (built in annotation)
#LoggedInUser
public boolean hasRight(Identity identity) {
return identity.isLoggedIn(); //or if he is in certain group of users
}
Context and Dependency Injection context (used in DeltaSpike).
JBoss Filters (a filter chain where you can create your own filter that, for example, checks if some IP is trying to send multiple calls within a very short period ~ 10 lines of code).
An example of the Filter
#Startup
#ApplicationScoped
#Filter(around= "org.jboss.seam.web.ajax4jsfFilter")
public class IPTrackerFilter extends AbstractFilter {
//IPTracker is your #ApplicationScoped bean that remembers all IP addresses accessing the application.
#Inject
private IPTracker fIPTracker;
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (!(req instanceof HttpServletRequest)) {
chain.doFilter(req, res);
return;
}
final String ipAddress= ((HttpServletRequest)req).getRemoteAddr();
if (fIPTracker.isBlackListed(ipAddress)) {
//implement error message here
sendErrorMessage(response);
return;
} else {
//all good, continue
chain.doFilter(req, res);
}
}
}
PS. I gave you the link for DeltaSpike, for others is really easy to find. Also, if you find DeltaSpike to obscure, try with JBoss Seam Security Framework.

Java Servlet POST action not receiving parameters from request

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.

A Spring MVC controller that delegates to a Servlet

One of my projects uses Spring MVC to handle URL mappings and dispatch logic. I have now to use a third party library which uses its own HttpServlet as the main entry point for its functionalities, but as it's an optional drop-in replacement for another library I can't just put the <servlet> declaration in the web.xml: I'd rather use a Controller and Spring profiles to switch between such implementations without having to edit the web.xml.
Is there anything offered OOTB by Spring to handle such cases? I don't seem to find it right away.
Thanks in advance!
Since registering the third party servlet in your web.xml is a no-go, I think your best bet would be to create a singleton instance of the servlet in your ApplicationContext, and then create a custom view that delegates to said servlet's service method.
You can see an example of custom views in action in this tutorial.
Answering my own question here just in case my approach can be useful to others.
There are two key factors I needed to consider:
the proper initialization of the servlet
give the servlet full control over the HTTP layer (e.g. setting HTTP headers, etc)
In my specific case there's no need for properly handling the servlet destruction, as it's a no-op.
I ended up writing a dedicated Controller, to be instantiated only if a specific Spring profile is activated, which takes care of instantiating and initializing the Servlet. Then, all the requests will be directly handled in a void handler method, as follows:
public class ServletDelegatingController implements ServletConfig {
private final DelegateServlet delegate = new DelegateServlet();
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
delegate.service(request, response);
}
// properly initializes the servlet
public void setServletConfig(ServletConfig servletConfig) {
try {
delegate.init(servletConfig);
} catch (ServletException e) {
throw new IllegalStateException("Failure while initializing the servlet", e);
}
}
}
The delegating-servlet.xml for the DispatcherServlet looks like the following:
<beans profile="custom">
<bean id="cmisServiceFactory"
class="com.foo.ServletDelegatingController"/>
</beans>

Categories