Using a Servlet for a non-servlet application - java

I know 'normal' Java, but am new to the world of servlets, containers etc. Because of that I am not sure which approach is most sensible.
Situation: I have created a Servlet that receives information and stores it in a database. This database gets read by other applications.
Now what I need is an application that receives the exact same information and stores it in the same database. However this new application needs to pull this information from another server (I'll be using httpClient for this) instead of it being pushed to it. Both applications will co-exist.
For this new applications I see the following two options:
Make a stand alone application. For this I can copy paste a lot of the existing back-end code, but I will need to make some modifications (the servlet container offers a context, easy database connection pooling etc.) Further I might need to use some wrapper so this can work like a proper daemon that I can start, but also gracefully stop/restart etc.
Make the new application part of a Servlet. That is: just start a new Thread in the init() of the servlet that will run the new application. This would allow me to reuse all the backend code I already have, without needing to rewrite any of it. I only need to write the code that does the HTTP-GET requests to the other server. With this approach it will also be easier to start and stop the service, because I can use the Servlet container for that.
Some info about the project: the backend code that parses and writes the data to the database has a few threads, but is not very complicated. Writing the code for the original servlet was about one week of work. With the existing code base I feel this new application should probably be 1, 2 days of work max.
The way I see it option 2 is easier. But it feels a bit like I would 'abuse' servlets.
So my question is: Aren't servlets for applications that should handle requests, instead of applications that make request? Are there some huge drawbacks I don't see here? Which option would make most sense?
tl;dr: Can I write an application that doesn't serve requests as a Servlet?

Don't copy and paste code.
Write a re-usable class/module which handles storing the information in the database which can be used by both 1) the servlet and 2) standalone code which retrieves information from a HttpClient.
This way the same piece of code handles the same logic - how to store the information in the database - whether the information in question is being pushed to a servlet or being fetched from a remote URL.

Servlet containers are thread-managed environments. In general, don't start your own threads in a servlet, or bad things can happen... starting and stopping the application context, for example - the appserver doesn't know about the threads you might have started so won't stop them with your app... (More detail in this SO question)
I would try to extract the logic I need from the servlet into classes that don't depend on the Servlet API, and redesign the servlet to make use of these classes. (Refactoring). The servlet API, as you note, is all about receiving requests and sending responses.
I can re-use the logic in my new non-servlet classes anywhere I like, including a non-servlet part of the application that polls out pull that info.

You could use, but you shouldn't, it is a very poor design.
If you have two different ways to access your application (one through servlets and other as standalone), you should create at leats three classes:
One class that does all the work relating database, etc.
One servlet that calls the first class
One stand alone class (or whatever) that calls the first class
In this way, you don't copy/paste, and you can reuse your code (even you can have a third way to call the class that do the heavy work

If you want to reuse code, have this code as part of a "Service" or "Business Logic" layer that will be used both by your servlet and non servlet application.
Package the code as a jar and use it in both applications.

Related

Implement Java Web Server with database, GCM and background threads

I am trying to create a web server that provides web service functions, communicates with android devices using GCM, uses a database and probably also has some background work to do.
I am currently unsure on the architecture of such a server.
I know how to create a simple web service, but have not found tutorials or descriptions that go beyond simple "Hello World" examples. As far as i know i can create a class with the #WebService annotation, and once deployed to e.G. Tomcat the server will create at least one instance of this class and provide the annoteted functions in this class as web services.
Now i wonder how to best implement database connection. From what i know the server would create an instance of this class for every request, wich will be garbage collected once the connection is closed. Since the web server needs the database for nearly every function it provides i think it would not be a good idea to create a database connection for every instance, but rather use a global connection to query the database.
From what i found out so far this could be achieved by injecting a class that handles the database connection as #Resource or #Singleton into the web service class.
But is this the proper way to do this ? Or am i worring too much and just creating a new database connection for each request is fine ?
Then i want to send GCM messages (the simple POST ones using the HTML google server), so i would probably create a controller or manager class to handle these requests. Would this also be injected as a #Resource or #Singleton into the web service class ?
And last but not least the server probably has to do some work periodicaly, wich would be some kind of background thread, that is independant of the requests the web service is recieving. Here i am at a loss on how to do this. A web service does not have a main() method i am aware of, so i am unsure on how to create this.
Can anyone give me a guick overview on how to design such a web server or can point me to documentation that describe on how to achieve this ?
All i found so far were simple examples that don't cover advanced stuff like this.
Ok, so you have 3 questions/problems.
How to create a Webservice
How to manage database connections
Execute batch process
All of this, in the same App. First of all, I should advice you to split into 2 app, one for consume (Web Services) and another for batch processing, including push notifications (IMHO). But lets go one step at a time.
1. Webservice: It's depends on the framework you choose. I usually made a choice between Spring-MVC or Jersey
2. How to manage database connections When you are querying a database, you usually don't want to open and close connections crazily. You want to use a connection pool. In a connection pool you'll ask for an open connection, will use it, and will free it when you are done. Normally, a connection pool is managed por the application server. If you want to manage the connections manually, you have to use a singleton to centralise acquiring and releasing.
3. Execute batch process You probably should use a singleton to manage batch process. This job manager will launch the job executions on other threads
Don't know if that answers your question/concern.. please let me know.
Ryu,
I found myself in a similar scenario. After going through the webs for over 2 days, I stumbled upon this solution of running a background thread which is triggered during the initialization of a servlet(init method).
Perhaps you can give this a shot and let me know if it works for you.
Here's the link which has an example to try - http://docstore.mik.ua/orelly/java-ent/servlet/ch03_05.htm
Cheers!

How are asynchronous requests handled by servlets?

I apologize in advance if this is a bad question.
I'm new to backend development and I'm trying to build an instant messaging service with GAE using java servlets.
And I assume the process for sending a message will be like this:
1. Client send JSON file to servlet.
2. Servlet parses the JSON file and archives the message to the database.
So my question is:
what's going to happen if the next user attempts to send another message while the servlet is in the middle of the process of saving the previous message to the database?
Because the arrival of user requests are not synchronized with the servlet cycle, will the new request just get lost?
Is there going to be some mechanism that queues the request or it's something that I'll have to implement myself?
I think I'm really confused about how the asynchronous request between different functions in a distributed system works.
And, if there any readings that you would recommend for backend design pattern? or just a general introduction?
Thanks a lot!
Please read the official tutorial on the subject that talks in depth about the java web technologies , web containers and servlets:
http://docs.oracle.com/javaee/6/tutorial/doc/bnafd.html
But to answer your questions :
When another HTTP request comes in , a new thread will be created by
the web container and will run your servlet concurrently.
The new request will be processed concurrently
The answer depends on your specific problem , performance and SLA requirements. The simplest solution would be to parse and write each request to the database. If you are dealing with a very large number of simultaneous requests coming in , i'd suggest starting a whole new discussion on the subject.
You need to know exactly what the 'Thread' is? When another request sent to Servlet. The container like tomcat will assign another thread for this request. Every thread is independent from another.
Server requests will run in parallel and your code might access/edit the same data concurrently. You should use Datastore transactions to prevent data corruption.
No, requests are independent and they run in parallel.
You could use Task Queues in your code to make updates run sequentially, but I'd advise highly against it: first Task Queue will double your requests, second it will force a distributed parallel system to run sequentially, basically negating the whole purpose of AppEngine.
Parallel processing are essential in server programming - they enable servers to process high amount of requests. You should write code that takes this into account - use datastore transactions to prevent possible data corruption in those cases.
in a servlet lifecycle the init() and destroy() methods are called only once - but the service() will be called each time a new request comes and hit the application and a new instance of the servlet will be shared with the request through a different thread . Therefore one of the most basic rules for creating a servlet is not to create global variable in a servlet class.
Your variable is readable/writeable by any other class. You have no control to ensure that they all do sensible things with it. One of them could overwrite it/incorrectly increment it, etc
The is one instance of a servlet, per JVM. So may threads may try to access it concurrently. Because it is global, and you are not providing any synchronization/access control, it will not be thread-safe. Also, if you ever run the servlet in some kind of cluster with different JVMs, then the variable will not be shared between them and you will have multiple loginAttempt variables.

Passing in objects to GWT servlets via servlet attributes (server-side) or "Dependency Injection"

How do I pass objects from non-GWT server-side code (e.g. regular server code) to the GWT "servlet" (still server-side code), specifically a RemoteServiceServlet?
My GWT server-side code consists of RPC-type RemoteServiceServlets to which I can't seem to get a reference so I can't pass in my real/fake object in testing mode or add servlet attributes. I can't see any way to simply pass objects in (dependency-injection style) as I have no access to the Server object as GWT seems to instantiate it deep within its internals, so what are my options?
P.S. I don't want to use a full-blown DI framework such as GIN/Juice - I find them to much magic. I just want a way to access the instance of a GWT servlet and pass stuff to it.
Let me start out by saying, if you haven't already, I highly recommend watching this Google I/O presentation on GWT Architecture best practices. I found it very useful and it's where most of the following came from.
What I did was create an abstract "dispatch" servlet that extends GWT's RemoteServiceServlet. Every module I have has only one service (that extends my abstract dispatch service) with which I register a set of request handlers. All GWT service calls for a given GWT module come into that module's dispatch service, which looks at the type of request and dispatches it to the appropriate request handler. The request handlers, in effect, handle the work that previously resided in the service servlet. Besides making your life easier by having fewer servlets to register in your web.xml (not to mention avoiding the extra interfaces GWT requires), you can more easily control the dispatcher object that handles all the actual dispatching. You can, for example, pass whatever real/mock object you like into these request handlers since you, and not the web container, are responsible for instantiating them.
And though I rolled my own, the gwt-dispatch project exists for this very purpose.
Hope this helps.
Servlet containers are designed to not allow direct access to the servlets that they host; that's why you've found it difficult to get any kind of handle to a servlet.
Rather, refactor the code that is currently in your servlets into separate request-handler classes, and have your serlvets call into them.
For testing purposes you can hook your testing framework, or your client code, to the request-handler classes directly. That's how people generally solve the problem you've run into.

Communication between two Web Services

I have a problem with web services. They are programed in Java and are running on a WASCE server ( both are on the same server).
My problem that i want to solve:
We have two Web services: App1 and App2
In App1 i want to call a function that is in App2. How can i do this? Is this even possible?
I tried creating a soapClient inside the App1 so i can connect to the App2 but that doesn't work.
exp:
I have a client that calls app1 gets data from app1 and send it to app2 then get back the response data from app2 and send it to an other function into the app1.
What i want to do is to skip the client part and do it directly so that app1 can send directly the data to the app2 and then receive an answer do whatever it needs to do.
For the note: Both of the web services use the connection to the database.
Thank you in advance.
(it has been edited with additional data)
What does "doesn't work" mean? Exactly what happens?
Start by generating some client code for App2. Can you use that from some simple Java environment, or say a Servlet. If that works, what happens when you try to call it from inside your App 1 Service implementation code?
However: if these are related services running in the same JVM can you not set up some simpler relationship using java libraries. My preferred way of developing a service is first to develop some useful Java code, and make sure that works, then "wrap" it as a Web Service. In which case I have a callable routine that can just be invoked as Java.
It's definitely possible, with differing levels of complexity and feasibility depending on exactly what it is you want, and the restrictions you place on it.
Probably one of the simplest ways to go about this, if you don't have a problem with the method in App2 being public, is to simply create a web service exposing that method and call if from App1.
If you want App2's method to be essentially "protected", so that it can be called by App1 but not by public clients, then there are several alternative options. Firstly, you could use firewalls or equivalent to prevent external requests to the service URL. Alternatively, you could expose the method through some form of interprocess communication; RMI would be the obvious native one for Java (set up an RMI method in App2 and export this through a manager, then obtain the reference in App1 and invoke the method remotely). Depending on exactly what it is you want to do, you may be better off with a framework that does all this under the covers; e.g. distributed objects through something like Terracotta.
You should give more detail in your question, though - currently the only thing you've really specified is that you want to call "a function" in App2 from App1. There are dozens (if not hundreds) of ways to go about this and the best one(s) will depend on the details of what you're trying to do.
EDIT (in light of comments): It's not the details of what you want to do that are lacking - I understand fine that you want to call some method in App2 from within App1. It's more the architectural details - what languages are both clients coded in, what libraries are you using to do the web services, are both clients on the same machine or separate ones (and if same machine, same JVM or not), are there any firewall issues that could inhibit certain kinds of connectivity, are there any office-political restrictions that could inhibit your options, are there any security restrictions that could do the same (such as whether you can expose the functionality of App2's method publically or not). All of these will shape what is possible and what is optimal - because at the end of the day, all networking is basically I want to use resources on that remote computer from here. Without more architectural specifics, there are literally dozens of ways that you could achieve this.
Regarding exposition: You would create a web service to expose App2's function in the same way you would create any other web service (with the details being dependent on the tool/framework you're using). As an example if you're using a tool that supports the JSR-181 annotations, you'd write a method in App2 that performs this function, and annotate it with #WebMethod. Then you'd ensure that if this method is not part of an existing webservice class you'd annotate its class with #WebService. I was presuming that since you already have a couple of web services, you'd know how to write/define them.
As for accessing the web service from App1, this can be done quite simply by a Java SOAP client. A tool such as WSDL2Java can create a stub class modelling the remote service that you can call; alternatively you can get a richer interface with something like CXF.
What WS library are you using currently, and what errors have you encountered when trying to use it to perform this interaction?

Java HTTP Proxy

I am working on a project where we'd like to pull content from one of our legacy applications, BUT, we'd like to avoid showing the "waiting for www.somehostname.com/someproduct/..." to the user.
We can easily add another domain that points to the same server, but we still have the problem of the someproduct context root in the url. Simply changing the context root is not an option since there are hundreds of hard coded bits in the legacy app that refer to the existing context root.
What I'd like to do is be able to send a request to a different context root (Say /foo/bar.do), and have it actually go to /someproduct/bar.do, (but without a redirect, so the browser still shows /foo/bar.do).
I've found a few URL rewriting options that do something similar, but so far they seem to all be restricted to catching/forwarding requests only to/from the same context root.
Is there any project out there that handles this type of thing? We are using weblogic 10.3 (on legacy app it is weblogic 8). Ideally we could host this as part of the new app, but if we had to, we could also add something to the old app.
Or, is there some completely different solution that would work better that we haven't though of?
Update: I should mention that we already originally suggested using apace with mod_rewrite or something similar, but management/hosting are giving the thumbs down to this solution. :/
Update 2 More information:
The places where the user is able to see the old url / context root have to do with pages/workflows that are loaded from the old app into an iframe in the new app.
So there is really nothing special about the communication between the two apps that client could see, it's plain old HTTPS handled by the browser.
I think you should be able to do this using a fairly simple custom servlet.
At a high level, you'd:
Map the servlet to a mapping like /foo/*
In the servlet's implementation, simply take the request's pathInfo, and use that to make a request to the legacy site (using HttpUrlConnection or the Apache Commons equivalent).
Pipe the response to the client (some processing may be necessary to handle the headers).
Why not front weblogic with Apache.
This is a very standard setup and will bring lots of other advantages also. URL rewriting in apache is extremely well supported and the documentation is excellent.
Don't be put off by the setup it's fairly simple and you can run apache on the same box if necessary.
Using Restlet would allow you to do this. The Redirector object can be used. See here and here for example.
If you instead serve out a JSP page you can use the tag to do the request server side.
Then the user will not even know that the resource was external.
http://java.sun.com/products/jsp/syntax/1.2/syntaxref1214.html
a bit more context for the API the client is working against would help here to give a solution that could work. Are you trying to provide a complete new API totally different from the legacy Java EE app? What artifact is serving the API (Servlet, EJB, REST service)?
If you have the API provided by a different enterprise application then I suppose you simply use a Pojo class to work as a gateway to the legacy app wich of cause can then be reachable via another context root than the new service app. This solution would assume you know all legacy API methods and can map them to the calls for the new API.
For a generic solution where you don't have to worry about what methods are called. I am curious if the proxy approach could really work. Would the user credentials also be served correctly to the legacy system by URL re-writing? Would you have to switch to a different user for the legacy calls instead of using the origin caller? Is that possible with URL re-writing. Not sure if that could work in a secure context.
Maybe you can provide a bit more information here.

Categories