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

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).

Related

Is it necessary to create both application-context.xml and application-servlet.xml in a single application?

Why do we require a application-servlet.xml at all ?
Why is application-context.xml alone insufficient?
Separation of concerns is just a best practice. No fire will suddenly appear if you ignore it, but you will have harder to maintain code. And if you carefully design your application with a web layer a service layer and a persistence layer, storing the beans in the proper application context will just make things simpler.
It not necessary but recommended. Using separated configuration files you can isolate the web from the other world for security reasons(e.g. more secure). You can make a spring-boot program even without a single configuration file by annotations.
The application context is a bigger context, it means the beans defined in this context can be referred by servlet context but not vice versa.

Dynamically extend Spring MVC powered REST api with access to application jar only

I am in a situation where I have a nascent rest api architecture where each method has tons of ceremony (validation, db connection acquisition/release, authentication), raw request/response objects as the parameters, and hard-coded json strings as the output. I want to use spring mvc to help with at least some of these issues (auth & db stuff i'll need to hold off on). This would render a lot of the current architecture unnecessary. This is pretty easy except for one feature of the current architecture: dynamically adding api calls.
The entry point (servlet) for the architecture reads from an xml file that contains the path for a request and a corresponding class to load. The class must implement an interface that contains an 'execute' method which has the logic for the request. The servlet calls this execute method after loading the class. This allows dynamic extension of the api as follows. The app is packaged as a jar together with the associated config (xml) files and given to a client. The client includes this jar in his project, creates a class that implements the aforementioned interface, and adds a mapping from request url to that class in the included xml file. He then runs the app and gets access to both the original api and his custom api.
Example:
Client is given app.war, interface.jar and custom-mappings.xml. app.war contains the implementation of the core api (rest webservice), and interface.jar exposes the interface BaseController that has the method 'execute' (app.jar also uses this interface in its controller). Client then defines his own class as follows.
package custapi.controllers;
public class ExtendedController implements BaseController {
public void execute(HttpServletRequest request, HttpServletResponse response) {
// LOGIC
}
}
He compiles this class and adds it to app.war. Next, he updates custom-mappings.xml with the following entry.
/custcall/mycall
custapi.controllers.ExtendedController
He then deploys the app. The controller provided with the core api receives the request /custcall/mycall, looks it up in custom-mappings.xml, finds the class is custapi.controllers.ExtendedController, loads that class, and finally runs its 'execute' method. This allows the logic defined by the client to be run.
Ideal:
Current architecture is replaced with spring-mvc. That is, there is no more 'super' controller that parses requests and delegates to the appropriate class and, finally, method. Spring handles this. For the app that uses this new architecture, the client would receive the app.war and the spring mvc deps that expose controller annotations. The client would then create a new spring mvc controller (taking advantage of validation, parameter -> pojo mapping, object -> json conversion), compile it, and add the resulting class file to app.war. His controller would then become an extension to the core api exposed by the app. When the app is deployed, he would be able to make a request /custcall/mycall like before and have it execute the logic he defined. This ideal scenario allows clean code for the core api (which I and others programmed) and an extended api. (A downside to this approach is that the client is tied to spring. In an even more ideal scenario, the client would use framework-agnostic annotations which are mapped to spring annotations by the app. I'm not sure how easy this would be.)
I'm not sure how the above would be realized with a spring-aware controller without sacrificing the benefits of spring. I don't believe the client could simply define another spring-aware controller (correct me if I'm wrong on this). The only solution I can think of is to have a spring-aware controller that has a wildcard path (e.g., /cust_rest/*) which acts exactly the same as the current controller. The client would not get any advantages that spring has to offer, but the core api would be a lot cleaner. I was hoping there was a better solution, however. Ideally the client would get the benefits of spring without having access to the core api source code. Any ideas on this, or is my solution the best that can be hoped for?
Thanks.
(NOTE: For both scenarios, I am only guessing how the client actually gains access to the dependencies/interfaces and deploys. I have only had access to the core api project for one day, and so my understanding of it is not complete.)
Related: Runtime loading of Controllers for Spring MVC and dynamically mapping requests/URLs
The above question looks pretty similar to mine. Replies are sparse (second one is just off topic, I believe).
Provided you setup classpath scanning properly there's no need for interface. Your clients can just annotate classes with #Controller #RequestMapping("/foo/bar"). Even if this class is located in its own jar it will still be scanned. If this is a REST service consider using #RestController instead to avoid having to place #ResponseBody on each handler method.
Use spring security to do declarative authentication & authorization (what you're doing now is programmatic security)

Runtime loading of Controllers for Spring MVC and dynamically mapping requests/URLs

We are starting a new project using Spring MVC, and we would like to move away from annotation-driven request/url mapping. We wish to implement the following use case:
Use Case A
User enters a URL.
The request mapping handler retrieves a list of mappings (e.g. from the DB), and based on this dynamic list of mappings, it calls the relevant controller.
This is because we want to be able to do the following as well:
Use Case B
We want to load a new Controller (perhaps a new reports module) into the web app without having to redeploy or do a server restart.
We will map this new Controller to a URL and persist it somewhere (most likely the DB).
We would like the Controller to be registered in the Spring app context (managed by Spring).
We would then like to use this new Controller in the request mapping.
We've taken an initial look at the different ways we can implement this, but we are unsure of the best architecture/method to go about this route. A couple of questions:
For Use Case A, how do we implement this within the Spring MVC framework (or if it's possible)?
For Use Case B, is there a good framework or way to be able to do dynamically loading and registering of this for web applications? We've taken a cursory look at OSGI but it seems to be advisable for use in non-web applications.
For Use case A :
Instead of DB you can keep the url mappings in a property file and then use property place holder to initialize beans using xml configuration on context up. This way remaining inside the spring framework, you can avoid annotations.
For Use Case B :
Tomcat supports dynamic reloading of classes but that to of only non structural changes in class file. But this has memory leaks as well as it doesnt cleans up old instance of class loader rather it creates a new instance.
Its quite achievable using spring-mvc-router API.
Please check below link
url-action mapping & routing in Spring MVC 3.0
Here the URL can be configured to controller.method using .conf file, but this can be achievable using java configuration, and i haven't tried so far.
Also if xml configuration chosen, then check out the property 'autoReloadEnabled', but its not adviceable for production use.
Hope this helps!!!

Dynamically add classes to Guice through reflection

Is it possible with Guice (and even in Java in general) to iterate over all classes in a particular package and add them to Guice?
The underlying problem: I'd like to be able to route all traffic to /admin/* to a single servlet which redirects accordingly. Then I'd like to be able to just add servlets to the same package and have them get picked up automatically. E.g. If I navigate to /admin/showCompanyDetails, I'd like that to redirect to a servlet called showCompanyDetails.java in the admin package.
Furthermore, I'd like this to work in such a way that all I have to do to add further admin functions is to drop a new class into the admin package. I.e. No factory methods to update and no containers to add to.
So far, the closest I've come is to have the redirect servlet create a Guice injector with a module that contains all the admin servlets. But as I said, I'd like to avoid having to update a Guice module.
Also, I'd like this to be possible in AppEngine.
And I want a pony.
There are some possibilities:
Use Servlet 3 #WebServlet annotations on your servlet classes, so they get picked up by a Servlet 3 web container. Then you can use Guice to inject dependencies, see here for an example.
Use guice-automatic-injection to bind your servlet classes in your classpath (they must contain their path similar to Servlet 3 via annotations or provide an accessor for it). Then you can create a Guice servlet module which retrieves all those servlets from Guice and registers them as servlets to their provided paths.
Both ways may be usable in AppEngine, but I haven't got experience with it.
Getting a pony is easy if you use just Object as its base class ;p

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