How do I implement the business logic of a MVC in a seperate class from the Servlet? - servlets

I have experimented putting the class in the servlets controller but I have trouble with the constructor and setting method access. I read its improves efficiency to have the business logic seperate, I even tried putting it in the JavaBean but I don't yet know how to send parameters from the controller to it. I still mave much to learn, just working on a project.

You can use EJB to separate business logic from Presentation tier i.e (Servlets and JSP) in JavaEE platform. If your project doesn't have much business logic code then simply use Java POJO classes. This example gives very raw idea. you can use web frameworks which have built in MVC design.
Controller:
Use Servlets to control navigation or perform other tasks against HTTP requests.
#WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
LoginManager loginManager=new LoginManager();
if(loginManager.isValidUser("getUserID from request Params","password from request params")){
//initialize user session and redirect to dashboard
//response.sendRedirect("/userhome.jsp");
}else{
//display failure messages. etc...
//response.sendRedirect("/login.jsp");
}
}
}
Model:
POJO which contains set of methods for login related operations.
public class LoginManager {
private Connection con;
public LoginManager() {
}
private void initConnection(){
//register driver class and create a new connection
//you can create separate DBUtils class to get new connections
//to prevent boilerplate code.
//make new connection to database
// con=..
}
private void closeConnection() throws SQLException{
con.close();
}
public boolean isValidUser(String user,String password) throws SQLException{
initConnection();
PreparedStatement pstm=con.prepareStatement("select 1 from users where userID = ? and password=?");
//set userID and password params
ResultSet rs=pstm.executeQuery();
if (rs.next()){
if(checkpassword.....)
return true;
}
closeConnection();
return false;
}
}
View:
pages like login.jsp and userhome.jsp pages are views;

Related

How to create Object in the class implementing HandlerInterceptor to access it from anywhere for that reqest

I am having situation like: in the preHandle() method of the class implementing HandlerInterceptor, i am having sessionId getting in the incoming HttpServletRequest object request. now using this session id i am fetching userInfo from the DB. the same info i have to use somewhere else like service layer to process the request.
It would be very helpful if anyone of you help me out to achieve it. Thanks in advance.
You can use a ThreadLocal to store a reference to a user that will only be accessible to the current thread of execution.
https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html
You can wrap this in a context class so that in your service you can access the current user via the static call: User user = UserContextUtils.getUser();
UserContextUtils:
public class UserContextUtils {
private static final ThreadLocal<User> CONTEXT = new ThreadLocal<>();
public static void setUser(User user) {
CONTEXT.set(user);
}
public static User getUser() {
return CONTEXT.get();
}
public static void clear() {
CONTEXT.remove();
}
}
The Interceptor:
public class MyHandlerInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
User user = null;// get user from the database.
UserContextUtils.setUser(user);
return true;
}
#Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler,
Exception ex) {
// as some web servers re-use threads, you must ensure that the
// context is cleared on completion either here or elsewhere.
UserContextUtils.clear();
}
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
}

Unity Container usage With multiple implementation

I have come up with a Question, that what is the usage of Unity Container or NInject if it is handled only for a single instance of an interface.
Ex: Generally we use like this
Public Class IEmailSender
{
Public Void SendEmail();
}
Public Class SMTP: IEmailSender
{
Public Void SendEmail()
{
// Send Email Logic using SMTP
}
}
Public Class OtherSender: IEmailSender
{
Public Void SendEmail()
{
// Send Email Logic for Other Sender
}
}
Public Class Builder
{
Public Static IEmailSender CreateBuilder(string senderType)
{
if(senderType.Equals("SMTP"))
{
Return New SMTP();
}
ElseIf(senderType.Equals("OTHER"))
{
Return New OtherSender();
}
}
}
In my Screen have two buttons
#1. Send from SMTP - Event(EventArgs)
#2. Send from Other Sender - Event(EventArgs)
Have the Same Logic in two Methods
IEmailSender emailSender = Builder.CreateBuilder(button.CommandArgument)
emailSender.sendEmail();
So, How these different scenarios will be handled with Unity Configuration in Unity Block
or NInject Binder,
Your feedback will be highly appreciatable.
In Unity, You can use named instances to register and retrieve different implementations of a single interface.
First You need to register concrete types to the interface using apriopriate names:
var container = new UnityContainer();
container.RegisterType<IEmailSender, SmtpSender>("SMTP");
container.RegisterType<IEmailSender, OtherSender>("OTHER");
After this you can use it in Your code:
IEmailSender emailSender = container.Resolve<IEmailSender>(button.CommandArgument);
emailSender.SendEmail();

how to add cache control headers to image served by spring mvc

I'm trying to implement a binary content controller in Spring MVC.
It's working okay but I want to add caching control headers to the response.
I checked this related question: Unable to cache images served by Spring MVC
But it's using a different method. I wanted to use this requestMapping - produces annotation. Here's what I have so far, but I'm not sure how to set the response headers with the cache control elements.
#RequestMapping(value="/binaries/**", method = RequestMethod.GET, produces={MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.IMAGE_GIF_VALUE,
MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
public #ResponseBody byte[] serveResource(WebRequest webRequest, String uri) throws IOException {
String path = (String)request.getAttribute( HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE );
BinaryFile bf = binaryService.findByUri(path.replaceFirst("/binaries", ""));
if (webRequest.checkNotModified(bf.getLastModifiedDate().toDate().getTime()))
{
return null;
};
return bf.getResource();
}
How about this:
public #ResponseBody byte[] serveResource(WebRequest webRequest, HttpServletResponse response, String uri) throws IOException {
response.addHeader("Cache-Control", "private, max-age=0, no-cache");
// ...
You could use ResponseEntity like this:
#ResponseBody
public ResponseEntity<byte[]> serveResource() {
//..
return ResponseEntity.ok()
.lastModified(lastModified)
.body(bf);
}
Or serve resources directly with Spring Resource Handling support.
Note that multiple HTTP caching improvements are scheduled for Spring Framework 4.2, now is the time to voice your opinion on this (you can comment/votes for issues).
So I just reimplemented the resource handling and thought I'd post the answer back to this question.
Basically I used the new ResourceHandling framework, and it was surprisingly easy to implement this.
Created a BinaryImage class that's backed by a CLOB in the DB. Implement the Resource interface from Spring 4.1+.
Then I created a new ResourceResolver that looks up the incoming requests against a known path "/images".
Then configured it in the WebMVC framework.
Code for 2 & 3 follows (1 is ommitted, it's straightforward to implement the interface):
/**
* The Frontend Binary Controller
*/
#Component
public class BinaryResourceResolver implements ResourceResolver{
private static Logger logger = LogManager.getLogger(BinaryResourceResolver.class.getName());
#Autowired
HttpServletRequest request;
#Autowired
BinaryImageService binaryService;
#Override
public Resource resolveResource(HttpServletRequest request, String requestPath, List<? extends Resource> locations, ResourceResolverChain chain) {
if (!requestPath.startsWith("/"))
{
requestPath = "/" + requestPath;
}
Resource bf = binaryService.findByUrl(requestPath);
return bf;
}
#Override
public String resolveUrlPath(String resourcePath, List<? extends Resource> locations, ResourceResolverChain chain) {
return null;
}
}
Then the configuration code: is in a config class that extends WebMVCConfigurerAdapter
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations(new String[]{"/resources/", "/products/", "/categories/"})
.setCachePeriod(30);
registry.addResourceHandler("/assets/**").addResourceLocations(new String[]{"/assets/"}).setCachePeriod(3600);
registry.addResourceHandler("/frontend/**").addResourceLocations(new String[]{"/frontend/"}).setCachePeriod(3600);
registry.addResourceHandler("/images/**").setCachePeriod(3600).resourceChain(true).addResolver(binaryResourceResolver);
registry.setOrder(-1);
}
You should provide last modified header while returning the byte array
if (webRequest.checkNotModified(bf.getLastModifiedDate().toDate().getTime()))
{
return null;
};
SimpleDateFormat dateFormat=new SimpleDateFormat();
response.addHeader("Last-Modified", dateFormat.format(bf.getLastModifiedDate().toDate().getTime()));
return bf.getResource();

Cometd with Spring-MVC for personalized chatting

I am working in a Spring-MVC application and I would like to include personalized chat as a feature in it. After some research I found out Cometd to be a suitable option. After going through the documentation and forever repeating samples, I have a little bit of setup which I have done. I need some help to integrate a personalized chat service in the spring-mvc app, and enabling private chat when user pushes chat button.
So basically, I found out, "/service/chat" can be used for private chat, so I have a class for that, and to use private chat, I must have a mapping of userid<-->sessionId, but I cannot find examples anywhere how to do it. I am posting some of the code I have, kindly let me know what is remaining to do, and if possible, some resources, samples for that.
Controller code:
#Controller
#Singleton
public class MessageController {
private MessageService messageService;
#Autowired(required = true)
#Qualifier(value ="messageService")
public void setMessageService(MessageService messageService){this.messageService=messageService;}
#RequestMapping(value = "/startchatting", produces = "application/text")
#ResponseBody
public String startChattingService(){
return "OK";
}
#RequestMapping(value = "/stopchatting",produces = "application/text")
#ResponseBody
public String stopChatting(){
return "OK";
}
}
Private Message Service :
#Service
public class PrivateMessageService {
#Session
private ServerSession session;
#Listener("/service/private")
public void handlePrivateMessage(ServerSession sender, ServerMessage message){
String userId = (String) message.get("targetUserId");
//Mapping code necessary to map userids to session-id's.
//ServerSession recipient = findServerSessionFromUserId(userId);
//recipient.deliver(session,message.getChannel(),message.getData(),null);
}
}
CometConfigurer :
#Component
#Singleton
public class CometConfigurer {
private BayeuxServer bayeuxServer;
private ServerAnnotationProcessor processor;
#Inject
public void setBayeuxServer(BayeuxServer bayeuxServer){this.bayeuxServer = bayeuxServer;}
#PostConstruct
public void init() {this.processor= new ServerAnnotationProcessor(bayeuxServer);}
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
System.out.println("Configuring service " + name);
processor.processDependencies(bean);
processor.processConfigurations(bean);
processor.processCallbacks(bean);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
return bean;
}
public void postProcessBeforeDestruction(Object bean, String name) throws BeansException {
processor.deprocessCallbacks(bean);
}
#Bean(initMethod = "start", destroyMethod = "stop")
public BayeuxServer bayeuxServer() {
BayeuxServerImpl bean = new BayeuxServerImpl();
// bean.setOption(BayeuxServerImpl.LOG_LEVEL, "3");
return bean;
}
public void setServletContext(ServletContext servletContext) {
servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bayeuxServer);
}
}
Cometd beans :
<beans:bean id="bayeuxServer" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop"/>
I have directly included the JSP files which have cometd configuration and setup from https://github.com/fredang/cometd-spring-example, and modified them to serve my needs. Kindly let me know what else is remaining, all suggestions are welcome, I am unable to find any examples for same task on net, which are detailed, and have more code then explanation. Thank you.
Using Spring 4.x's new WebSocket feature would definitely work; moreover, this new module ships with lots of very interesting features for your use case:
STOMP protocol support
messaging abstractions
session management
pub/sub mechanisms
etc
You can check this nice chat application that demonstrates all those features.

Spring MVC test case

Am new to Spring MVC, i have written web servise using spring MVC and resteasy. My controller is working fine, now need to write testcase but i tried writtig but i never succed am also getting problem in autowiring.
#Controller
#Path("/searchapi")
public class SearchAPIController implements ISearchAPIController {
#Autowired
private ISearchAPIService srchapiservice;
#GET
#Path("/{domain}/{group}/search")
#Produces({"application/xml", "application/json"})
public Collections getSolrData(
#PathParam("domain") final String domain,
#PathParam("group") final String group,
#Context final UriInfo uriinfo) throws Exception {
System.out.println("LANDED IN get****************");
return srchapiservice.getData(domain, group, uriinfo);
}
}
can anyone give me sample code for Test case in spring mvc.
"Spring-MVC" Test case could seem like this using mock objects, for example we want to test my MyControllerToBeTest:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/spring.xml")
public class MyControllerTest {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MyControllerToBeTested controller;
private AnnotationMethodHandlerAdapter adapter;
#Autowired
private ApplicationContext applicationContext;
#Before
public void setUp() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
response.setOutputStreamAccessAllowed(true);
controller = new MyControllerToBeTested();
adapter = new AnnotationMethodHandlerAdapter();
}
#Test
public void findRelatedVideosTest() throws Exception {
request.setRequestURI("/mypath");
request.setMethod("GET");
request.addParameter("myParam", "myValue");
adapter.handle(request, response, controller);
System.out.println(response.getContentAsString());
}
}
but i don't have any experience with REST resource testing, in your case RestEasy.
If you want to test the full service inside the container you can have a look at the REST Assured framework for Java. It makes it very easy to test and validate HTTP/REST-based services.

Resources