Undertow: Using existing Servlet instance - java

I am trying to replace in an existing application the embedded web server with Undertow as the old does not work correctly in some cases.
The embedded web server is used to server a few simple servlets. My main problem is that I can't find a way to register an existing HttpServlet instance in Undertow.
All API methods I was able to find only accept an Class<? extends Servlet>. Also the servlet tutorials and others only use Class<? extends Servlet> for registering a servlet.
My Servlets however already exists and I need to use them directly as each servlet is already configured with certain parameters and thus can not be created by just providing a class name.
Is there any way to use an existing instance of a class that implements javax.servlet.Servlet directly in Undertow or is Undertow not usable for such a case?

It is possible to use an existing Servlet instance in Undertow by using the method Servlet.servlet(String, Class<? extends Servlet>, InstanceFactory<? extends Servlet> servlet):
Servlet myServletInstance = ...
Servlets.servlet("MessageServlet", MessageServlet.class,
new ImmediateInstanceFactory<Servlet>(myServletInstance))
.addMapping("/*")
In this case the class parameter is ignored and instead of creating a new instance via constructor by Undertow internally, the provided servlet instance is used.

Related

Jersey 2 - Request scoped binding vs Singleton binding

I'm learning Jersey and trying to build a rest api. But I'm having a hard time understanding the difference between various bindings - bind() , AbstractBinder(), bindFactory() and also the scopes - RequestScoped , Singleton and PerLookup. What are the differences between them and when to use which one?
e.g. Say I have some request specific data passed into the request header. I want to use this data multiple times (say in resource classes, DAOs etc) during the request processing. What I figured is that I'll use a request filter and extract the data using the ContainerRequestContext and store it to some class. But i'm not able to figure out how to bind this class so that I can access it later. Which binding to use in this case?
bind() and bindFactory() are methods in the AbstractBinder class that you use to bind your services in the registry. The AbstractBinder is what you register with Jersey so that it knows to configure all your bindings. You use bind() to bind the service itself. You use bindFactory() to bind the service using a Factory (or Supplier in 2.26+) to create the service.
RequestScoped means that the service is scoped to the request, meaning that it will be the same instance for the lifetime of the request. You would use this scope when the service is dependent on information tied to a request, like request headers.
Singleton scope means that there will only be one instance of the service for the lifetime of the application. You would use this scope when the service can safely be used at anytime without being tied to any request.
PerLookup means that a new instance of the service will be created every time it is looked up, either directly through the ServiceLocator (or InjectionManager in 2.26+) or via an #Inject (or other injection) annotation. Even though this is the default scope, the RequestScope and Singleton scope would be more appropriate for most of the use cases in the context of a Jersey application.
For your use case where you want to get information from the request context and use it in the service, you would use a RequestScoped service and use a bindFactory() with a Factory (or Supplier in 2.26+) and inject the request context into the Factory and use the context to create your service. You can see more explanation in How to inject an object into jersey request context?. If you are using Jersey 2.26+, you'll also want to read Jersey 2.26: register #Inject in ResourceConfig bindFactory cannot convert Factory to Supplier

Basic on servlet

When do we implement Servlet Class and When do we implement GenricServlet class as both of them are for life cycle methods?
and my sir told me that GenericServlet class is a helper class,so if we have to use GenricServlet class then whats the need of the Servlet interface?
Do we use Servlet class also without the help of GenricServlet?
Servlet is an interface and GenericServlet is a abstract class which implements Servlet, ServletConfig & Serializable.
GenericServlet class provides default implementation for all the methods in Servlet interface except the service method. So if you extends your servlet class from GenericServlet, you can only implements the service method and override those methods that you care about. It saves some time.
And of cause you can implement Servlet class without the help of GenericServlet.
Servlet is an interface defining what a servlet should implement.
GenericServlet is a generic, protocol-independent servlet.
HttpServlet is a servlet tied specifically to the HTTP protocol.
when to use
In general, you'd extend HttpServlet to implement an application's web layer.
You can also implement Servlet if you're writing your own container or handling everything yourself.
You can extend GenericServlet to handle a different protocol,by using the features provided by the container, but you might not.

How do i call Post method of HttpServlet from GWT servlet?

I have two servlets, one is a GWT Servlet which extends RemoteServiceServlet and second is BasicServlet which extends HttpServlet. So my question is how do i call post method of HttpServlet from GWT Servlet. And here I confirm, I don't want to redirect to servlet using RequestDispatcher, I want to create a new Post call with new parameters.
Please guide me in right direction.
TIA!!!
Seems like an odd thing to do. Can't you put the code you want to execute in a third class/service and call it directly?
If they are on different servers (or some other reason) then you could use HttpClient (or similar)?

Can we replace the purpose of init method to the servlet constructor?

Can we replace the pupose of init method to the servlet constructor?
My question is why does servlet need a separate method int(ServletConfig config) for the pupose of initialization we could have achieve the same thing by having a parameterised constructor let XServlet(ServletConfig config) and the container can invoke the same .
Probably because you cannot specify the parameter signature for constructors in an interface.
It is generally considered a bad practice to perform logic in constructor (it should only initialize the field and create object in consistent state). It also makes testing harder.
Also it is much harder to perform injection - when using init the container can create a servlet, inject dependencies and run init. With constructor you would expect to have all the dependencies already set. Wicket works around this problem by injecting Spring beans into page class from superclass constructor - because superclass constructor runs first. However modifying subclass fields from superclass constructor seems wrong.
That being said using separate init method some things simpler and easier to maintain. Also note that EJB promotes #PostConstruct annotation as well.
I guess this choice was made to simplify the coding of servlets. In the current situation, a servlet having no need for specific initialization can be coded like this:
public class MyServlet extends HttpServlet {
// doGet, doPost, etc.
}
If the servlet was initialized using the constructor, it would need to be coded like this:
public class MyServlet extends HttpServlet {
public MyServlet(ServletConfig config) {
super(config);
}
// doGet, doPost, etc.
}
BTW, they even introduced a no-arg init method that can be used to avoid being forced to call super.init(config).
Short answer: NO.
Long answer:
If a servlet contains a constructor and a init method, you will see the constructor is called first, and then the init method (try it out with sysout statements).
A servlet is a java class, so it must follow the java process, so constructor is called first and then the init method (note that the init method is called by your servlet container like tomcat because that's how servlet's are supposed to be initialized; read the servlet specification).
So, if you need to do some operation that is specific to your business need (say create an DB connection or read a set of user details etc); constructors are not the best place to put these things in.
Usually constructors should never have any complex logic/business processing. They should initialize bare minimum member variables and leave the complex things to later; in case of servlets the heavy lifting can be done by init method.
Also note that by the time the init() is called the servlet container is up and ready with it's system resources, i.e it would have initialized the JNDi name bindings, data sources so on and so forth.
So in a way it guarantees you that when you call the init(), it will have the system resources ready for you to work on.
The servlet 3 spec says this:
2.3.1 Loading and Instantiation The servlet container is responsible
for loading and instantiating servlets. The loading and instantiation
can occur when the container is started, or delayed until the
container determines the servlet is needed to service a request. When
the servlet engine is started, needed servlet classes must be located
by the servlet container. The servlet container loads the servlet
class using normal Java class loading facilities. The loading may be
from a local file system, a remote file system, or other network
services. After loading the Servlet class, the container instantiates
it for use.
2.3.2 Initialization After the servlet object is instantiated, the
container must initialize the servlet before it can handle requests
from clients. Initialization is provided so that a servlet can read
persistent configuration data, initialize costly resources (such as
JDBC APIbased connections), and perform other one-time activities. The
container initializes the servlet instance by calling the init method
of the Servlet interface with a unique (per servlet declaration)
object implementing the ServletConfig interface. This configuration
object allows the servlet to access name-value initialization
parameters from the Web application’s configuration information. The
configuration object also gives the servlet access to an object
(implementing the ServletContext interface) that describes the
servlet’s runtime environment. See Chapter 4, Servlet Context for more
information about the ServletContext interface.
Read this part:
The servlet container loads the servlet class using normal Java class loading facilities.
so, the container will have to use standard java class loading mechanism. Which means it can not do what Duncan have just suggested.
int(ServletConfig config) is a life cycle method of Servlet.and it is being called by servlet container.
We can replace the init method code in parameter constructor of super class servlet.
but we can't force the developer to call super class constructor
for example
/*If generic servlet has a constructor like this*/
public GenericServlet(ServletConfig config){
....
}
/*And Developers servlet is calling only default servlet.*/
public MyServlet(){
super();
}
So in this scenario initialization never happens for that servlet. it cause issues problem. because ServletConfig obj is not initialized.
And we cant force the user to call specifict super class constructor.
The simple answer is that you have to have a no-arg ctor and an init method because that is what the spec requires...
Why the spec is written like that is probably a matter of history. These days I think that we might defer construction until the ServletContext is available and call a ctor with that argument. But looking back there was a ServletContext.getServlet(name) method, so that one servlet could look up another on initialisation and communicate with it. For this to work they would all have had to be created up-front and then init'd.
getServlet was deprecated and now returns null (I think it was a security hole for containers that were running multiple apps).

Abstract types in webservice definition (wsdl)

I'm using the framework xFire to publish a webservice in my web application. In this service I use abstract return types in the operations like List<GlobaleType>. The operations concrete return values are ArrayList<SpecialType>.
The concrete class SpecialType extends the abstract class GlobaleType. In the generated WSDL document only GlobaleType is given, with the additional definition, abstract="true". A generated client (with the help of apache axis) creates only an abstract class GlobaleType which can't be used for instantiation.
Has someone an idea why the wsdl contract is wrong?
If I understand you correctly, your web method signature is:
public List<GlobaleType> doSomething(args)
Then your wsdl is being generated correctly. As long as apache axis knows that the SpecialType extends hte GlobalType, then the final type can be sent across the webservice and the polymorphism will be transfered from the web service to the client.
Are you using a JAX-WS web service? Then make sure that you use the #XmlSeeAlso annotation on your base type.

Categories

Resources