retrieve jsf bean in axis2 web service as server request - java

I am using eclipse axis2 to create web service client from wsdl.
My impl method is:
public Output[] startProcess(Message[] Messages){
MyApplicationBean managementBean = (MyApplicationBean) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("myapp");
...
}
However when I execute:
http://localhost:8080/MyProject/services/portStartProcessService with method startProcess
I see in tomcat debug that it reaches my method, however the FacesContext.getCurrentInstance() returns null.
My web.xml (part of it)
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
How can I use JSF beans (like application scope) in web services call?

I know you do not want to hear this just yet, but you got the architecture wrong. JSF application context is useless with web service calls, because the whole idea of JSF is that GUI is built of stateful components stored:
in user session, or:
in a hidden form field.
Since neither session nor forms are available to web service calls, JSF does not apply here. You might as well ask how to make a web service that presses a JButton or inserts a CD into your CD-ROM.
I understand that you do not need the JSF components, but rather need some application logic that resides inside one of the managed beans, right?
Well, The easiest solution is to get a time machine, go back in time to when the project was planned and tell the architect that YOU NEVER PUT APPLICATION LOGIC INTO MANAGED BEANS. One of the reason is that they are unavailable to web service calls. Your application logic should reside in the service layer, provided by Spring or EJB.
Both Spring beans and EJBs are easy to reach from Axis services and from managed beans, and so you never need to access JSF managed beans from any place else than JSF front-end. If you do not like Spring and can't use EJB for some reason, build your service layer from POJOs, set it up in ApplicationContextListener and register in the application scope.
If such clean solution is unavailable and refactoring is impossible, you have two choices:
if the managed beans you try to reach are application scoped and eager, then they can be accessed in a JSP way, from the application context, using the venerable getAttribute method (you can access application context through the servlet context, which afaik you access through the message context, which in turn you access by the static MessageContext.getCurrentMessageContext method in Axis).
if the managed beans you want to use are request scoped and require some JSF plumbing (so you can not instantiate them by yourself) then you can pretend to be a FacesServlet and create the faces context by yourself; it is tricky but doable, a good and quite famous description is here: http://www.thoughtsabout.net/blog/archives/000033.html. You need will need servletrequest and servletresponse (from MessageContext). You can probably skip the parts required to pass the FacesContext on, because you will not require it to process any views.
Disclaimer: I never tried the last solution - it seems to work, although it is pretty dirty (and actually causes your web services to depend on JSF, which is bizzare).

Related

How do I perform one time actions in a Java Webapp AFTER all servlets have been initialized?

I have a standard Java 11 Web application, with multiple servlets in it. Some servlets are imported by libraries, others are written within the application itself.
I need to perform a task AFTER all web servlets have been initialized, preferably before any requests come in. The task requires access to ServletContext.
I have tried performing this by creating a ServletContextListener and it's corresponding contextInitialized method, but this performs the task BEFORE the servlets have been initialized.
I cannot add the task to the last servlet to load, as the last servlet loaded is imported from an external library.
It would be preferable if the solution does not involve creating a servlet with no mapping.
If you have access to your deployment descriptor (web.xml) and the servlets are eager loaded, then you could append your servlet in the servlet list and set a high number in load-on-startup element.
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.project.LastServlet</servlet-class>
<load-on-startup>99</load-on-startup>
</servlet>
I tried to find a workaround in the documentation, but I couldn't find it and the ServletContextListener is a no go:
"All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized."

Asynchronous service calls on server startup

I'm trying to create a simple RESTful application that helps people create and retrieve certain objects. The objective of the service is to serve up these objects as quickly as possible, which is why I'm considering cheating a little by "pre-creating" the objects during the server startup time in an asynchronous fashion. I can get away with this model because I know that there are only 500 different flavors of objects that people can ask for so i'd rather have them readily sitting in my persistent store (redis) warmed up such that by the time a user is asking for it, it's ready to serve.
My question is around how to enable this "background/async" processing right around the server startup (for a server like jBoss/tomcat in a RESTful service written in java). Putting it into a static block in the class serving results doesn't work, so I was wondering if there's a config in the catalina files that can link to loading a class which in turn could do the needful.
I think you may be looking for load-on-startup in your web.xml file, and then if you use the Init method in your HttpServlet class you may get the behavior you want.
Load-on-startup is a directive to tell the container to start that class immediately upon startup.
<servlet>
<servlet-name>ServletOne</servlet-name>
<servlet-class>com.yourcomp.MainServlet</servlet-class>
<description>This servlet is an example servlet</description>
<load-on-startup>1</load-on-startup>
</servlet>

What does it mean in Spring 3, web-aware application context

I am trying to setup a session scoped bean but the spring document said that session scope is only applicable on web-aware application context. No further explanation in the doc. Can someone clarify this?
This means that you can only use the session scoped beans in a an application deployed to a web server. Spring can be used in applications that run in standard JVMs along with applications that run in servlet containers (Tomcat, etc). Session, however, only exists in web servers so it has no meaning if the application is running in a standard desktop environment.
There are basically 5 types of scopes available for spring bean.
1)Singleton
2)Prototype
3)Request
4)Session
5)Global-Session
The first two scopes can be used with any type of spring applications.
But the remaining 3 are related to web applications. They can be used only with the spring applications which are involved in web.
Web aware means when the application provides web endpoints for third party client. I.E When the application contains at least one RestController . You can do this by simply adding #RestController annotation to your class.
ApplicationContext is an interface, spring ships multiple ApplicationContext implementations, according to documentation you need to use one that is web-aware.
The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown.
And as of spring framework core (6.0.4) further configuration might be required:
To support the scoping of beans at the request, session, application, and websocket levels (web-scoped beans), some minor initial configuration is required before you define your beans.
...
If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state.
If you use a Servlet web container, with requests processed outside of Spring’s DispatcherServlet (for example, when using JSF), you need to register the org.springframework.web.context.request.RequestContextListener ServletRequestListener. This can be done programmatically by using the WebApplicationInitializer interface. Alternatively, add the following declaration to your web application’s web.xml file:
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
Spring boot will automatically configure this for you (couldn't find documentation mentioning this explicitly).

Spring Web Application - How to get from page controllers to business layer

I am writing a Spring web application in Eclipse. In WEB-INF I have a web.xml file that gives a servlet mapping for a myapp-servlet.xml file.
In myapp-servlet.xml, I have a bean for a page controller. I surmise that the Spring DispatcherServlet instantiates these beans from its own ApplicationContext. When I run my project as a server, it displays the index.jsp file - "hello hello hello".
Now I also surmise that were I to put a submit button that sends post data in this index.jsp file, my page controller would be notified of the HTTP request. However, how can I interact with the rest of my application (the business layer) from the page controller? I am writing an LDAP Directory Lookup application, and once the user inputs a name I want to return an email. So, when the user inputs a name and hits submit, I want to communicate with my LDAP business layer. How can I do this?
One way I have thought of doing this is to add my business objects as properties to the page controller in the myapp-servlet.xml file. However, this seems to integrate the business layer and the controllers far too much for my liking - it means that every controller would need properties for business objects.
Another way I have thought of doing this is to create a kind of factory that all controllers have listed as a property in their XML. Through this factory, the controllers can access business objects; the factory is the interface between the two layers.
These are both custom ideas, and I suspect that there is a pre-made solution. Is there already a method of going about this? (Integrating business layer with web / page controller layer?) Or is it up to the programmer to concoct a custom solution as I outlined above?
Thanks, (and sorry for the long question - hence the bold)
ktm
Your controller needs to somehow hold a reference to your business objects. To fully benefit of Spring, you will want to inject those dependencies into your controller.
This is not tight coupling, especially if those business objects implement an interface and your controller will only know about that interface.
Dependency injection eliminates the need for factories as you will need to know about the service interfaces with our without a factory:
SomeBusinessServiceInterface service = businessFactory.getBusinessService();
But think about it like this: you must somehow get a reference of some service (using that service interface for low coupling) and most likely you need to cache that -- store it as an instance variable. Since you have that anyway, providing a setter does not couple your web and business tier any more than they already are.
If a setter seems unnatural (and it sometimes is) use constructor injection to implement this as classic OO aggregation.
Regarding the application context config, Spring allows you to define a webapp-wide application context defined using a ContextLoaderListener in web.xml. This is usually where all your business bean definitions should reside. Your -servlet.xml application context is bound to the servlet and should usually contain MVC stuff, referencing the beans in the root context as that context automatically becomes the parent of all the -servlet.xml (therefore all the beans there are visible for your servlets).

Using pure servlets (Java Servlet, no framework) in a project using the Spring framework?

We've got some Pure Servlets (pure Java classes following the Servlet API, no framework) that we'd like to include in a project that relies heavily on the Spring Framework.
What's the best way of including these servlets in the project, when all the new code we're writing is making heavy use of Spring 3 features?
your servlet container can run multiple servlets, spring is just one of them. why not just include your servlets in the web.xml and see if it works? it should work. spring is not that intrusive, yet (but obviously it already intruded the minds of many developers)
If you declare servlets in the web.xml, alongside the Spring front controller, it most certainly will work.
You just have to be careful when you declare which URLs map to the servlets. If you send "/*" to the Spring front controller, none of your requests will reach your other servlets. Be specific about what you need to send to each one.
As you might know, servlets cannot be configured as Spring beans. If your question is about colloborating with spring beans from a servlet, do refer this thread and also this
Spring provides a couple of classes to make this bridging easier.
ServletForwardingController
Spring Controller implementation that
forwards to a named servlet, i.e. the
"servlet-name" in web.xml rather than
a URL path mapping. A target servlet
doesn't even need a "servlet-mapping"
in web.xml in the first place: A
"servlet" declaration is sufficient.
Useful to invoke an existing servlet
via Spring's dispatching
infrastructure, for example to apply
Spring HandlerInterceptors to its
requests.
ServletWrappingController
Spring Controller implementation that
wraps a servlet instance which it
manages internally. Such a wrapped
servlet is not known outside of this
controller; its entire lifecycle is
covered here (in contrast to
ServletForwardingController).

Categories