Usually, a user makes a search, get a hitlist, and can then browse it. The hitlist is an intermediate result that remains consistent throughout the browsing and is typically stored in session state. E.g. if new items are added concurrently by some other, they would appear only in a subsequent search.
In a REST application, I can't have this intermediate result easily -- neither does it belong to the client, nor the model. I have read Pagination in a REST web app, but am not completely clear with the answer. The solution there seems to assume that the model is not updated while the user browses the results.
We can of course imagine the world (the model) as series of immutable snapshot. By providing a timestamp (or a global version number), we then get a consistent view of the model at that time, which solves the problem from a conceptual point of view. It does however imply full versioning of the model. (I'm also wondering if there is a connection to draw with functional programming)
How should I deal with this issue?
Note: I'm asking because I plan to use the play framework, which has no notion of HTTP state or session at all; it's pure restful.
After you've got query result on the first search, You can save the result in a cache. For one server it can be ehcache (supported in play) or memcached (also supported by play) for a cluster environment. You can save the result by a static name + session id. So you only need session id for each request, it's saved in the client cookie and available in your play app.
You can use cached data for browsing pages. I'm also recommending ElasticSearch.
EDIT: A better way is you can use play-search http://github.com/jfp/play-search, Sample:
Query q = Search.search("object:dogs", Folder.class);
q.orderBy("object")
.page(2,5)
.reverse();
PS: Your decision with Play is perfect. I'm a professional .net developer and I can say the only (optimal) web framework in the world that can race with asp.net mvc 2 is Play framework. Grails is buggy, Django/Python, Yii/Php, Rails all are slow, not type safe and far from jvm/clr frameworks. wicket, tapestry, struts, jsf, spring mvc all are verbose and useless. spring roo is only a template generator. Asp.net mvc surpassed asp.net and became #1 development platform for .net, but sun worked for an old asp.net clone with jsf for next gen, big mistake. The only hope for java is play framework in my opinion. With scala module, it's perfect...
I'm kind of lost about what your context is, but if I have to provide a short answer, it is that search results should be part of the model. I assume you have a searchable model. What you do is index the parts you need to search and store the index info (making it part of the model, too). When you execute a search, you query the index and display results. Performing the search a second time would not contain newly added items, unless the index is regenerated.
This removes the need to use any session state and keeps it restful, as the indexing is just another operation performed on a resource. Is this what you need?
Related
I have a legacy banking application coded in Struts 1 + JSP
Now requirement is to migrate the backend (for now MVC) to Springboot (MVC).
Later UI (JSP) will be migrated to angular.
Caveats
1.) Backend is not stateless
2.) Lot of data stored in session object
Approach
Have 2 application running in parallel (Struts and Spring), and share the session object between the two, Storing session in Database, in memory (Redis) etc. This means lot of code changes, as currently session is manipulated across layers of JSP, action, service for every update/fetch
Build complete Spring application and then make it live, which is again not feasible and we can't have user waiting.
Marry Struts 1 and Spring in same app and later Divorce them, and removing struts components progressively.
Question
Is it feasible to have Struts 1 and Spring together in same web application.
Can 2 different servlets (ActionServlet & DispatcherServlet exists together), possible if i have 2 different context paths for spring & struts
Currently focus is to migrate MVC layer, service layer will not be an issue.
Also if i need to keep backend design of API to support REST in future, possible if i can design in such way.
Current
JSP -> Struts 1 MVC -> Service Layer -> DB
What we can built
JSP -> Struts 1 MVC <-> JSON Object parser <-> Spring REST MVC -> Service Layer -> DB
Future
Just remove JSP -> Struts MVC
Angular (or any other framework) -> Spring REST MVC -> Service Layer -> DB
My friend, it is so good to read your question! I lived the same hell you are about to enter using the very same stack...
Approach 3
Honestly I would never try it. The reason would be simple, we wouldn't want the risk of having old project and new project mixing with each other. Libraries from the legacy are very likely to conflict with libraries from the new project (same libraries, different versions) and you would then need to either refactor old code to allow use of the new version, or change libraries completely.
When migrating, you will want to keep your work on the legacy code to a minimal, to none if possible.
Approach 2
The perfect one, but as you said, it won't pay the bills. If you have the cash to work on it, then great, go for it, otherwise, you are for...
Approach 1
Strangulation, that's what worked for me. Start with a working shared login and then move to small functionalities. Think of a tree, you start by removing some small branches, them you move to nodes, until you are able to cut everything. As you remove the small functionalities, they should be made available on the new product (obviously you can't disrupt service otherwise you would go with approach 2).
More specifically, my suggestion is:
Back-end
1) Get the login working. In my case, legacy was all about session, but we didn't want that on the new product. So we implemented a method on the legacy code during login, which would call Oauth from the new product and store in the database the login information, just as you mentioned. The reason for this is on the front-end part of my reply.
2) Define how your legacy and back-end will live together and the resources to have both of them working (ram and CPU to be more precise).
2.1) If by any chance, your legacy runs on tomcat with custom libraries, you might have problems running your new product in a different context. If that happens, my suggestions, go for Docker (just get a close look on memory usage and make sure to limit them on your container(s)).
3) Start very small, replace functionalities related to creating new stuff which hold little to no logic (small crud, such as users, etc) then move to things that have mid-sized logic or that are really ugly on the legacy product and are used on day-to-day basis by your end-users.
4) All of the rest (by the time I left the company, we were not in this phase yet, so I can't provide much info on that).
5) Don't treat this project as a migration only. Get everyone on the page that this a new product. Old code should not be copied and pasted, it should be understood and improved using best practices.
5.1) Unit and integration tests as soon as possible, if your legacy have them, GREAT, compare results to make sure your refactoring didn't break anything or changed the expected outputs. THIS IS ESSENTIAL.
Front-end
1) Once you have the "unified" login working, you will be able to load the pages from the new product as if they were part of the legacy (you could even add a frame on the jsp of the legacy that will load your angular page, we did it and it works like a charm).
1.1) Not cute from a UI/UX perspective to have old and new pages, but it will add value to end-user and provide you with feedback from them once you release the pieces to production. Since your legacy now have access to the token (or whatever auth method you are using, that will be feasible).
2) Define the styles from the beginning. Don't get the job of UI/UX to later (like my team did). The sooner you figure out things such as colors, design, icons, etc, the less time you will waste on meetings that should discuss the release and its impact but are wasted discussing "this is not the color I wanted" or similar. Honestly, get UX defined before UI and make that crystal clear.
3) Design it as if you were designing a micro-services front-end. You might take a lot of time to get to that point, but if and when you do, the migration from the new architecture to micro-services will be much less traumatic.
Culture
I don't know the culture of your workplace, but mine was far from perfect, old people with old thinking into their comfort zones.
Get to change the workplace culture to adapt to what we currently have on the marketplace, old people sometimes tend to resist change, specially when they are technical and do not update on what's new out there. It will make much easier to replace people when they leave the company (because people do move on).
I heard they are still trying to run Scrum (as I mentioned I am no longer there), so there was a huge headache for developers defining What and How the migration of functionalities will take place.
Those are my two cents, hope they help you in some way, and I wish you the best of luck.
Since option 2 is not considerable because of business feasibility let’s talk about the other two.
Approach 1
If you push your session state as far back as appropriate datastore ( Redis/Memcache) and use a transparent mechanism to get the
session data and update any changes made by app server then you would not need to change any code interacting with session.
Any call to get session object from any piece of code in your application is delegated to container and it is container which
provides you with the object ( usually a mapping of sessionid and object is maintained). For container such as Tomcat I am aware of
session manager which can be replaced by just putting the jar in the container and pointing the config to the backend store. I have used
memcache based session manager successfully in production for a high traffic internet application.
Check this for Redis (https://github.com/pivotalsoftware/session-managers) and Redisson Tomcat manager (https://github.com/redisson/redisson/tree/master/redisson-tomcat), Memcache (https://github.com/magro/memcached-session-manager)
Using this will tranparently fetch/store session in respective datastore without changing any session related code in your application.
So the request with session id in cookie can land up on any of the tomcats ( hosting struts or Spring MVC app) and get the session
fetched from the backend store, made changes upon and tranparently stored back.
Approach 3
Is technically possible ( they are after all different servlets with different configuration responding to different url patterns)
but opens a lots of problems areas in terms of
dependency jars conflicts. But if you freeze the library versions of both the framework during the migration and somehow don't get any
conflict with a certain versions of your mix then it can be worth trying as eventually the struts library and it's dependencies will go away.
As for the Angular part - you can still still have the user info in the session and rest of the stateful interaction will need to be designed
in a series of stateless ( stateless on the middle tier as eventually you will need some state - just that it will be pushed to the database) interactions.
At work, we develop a web application using Vaadin. I am a pretty advanced programmer in Java. I’m experienced with Vaadin as well. But now I've come to a point where information needs to be stored in a user session. Attributes like Locale, Username and so on.
In the Vaadin Documentation they are talking about two different types of sessions but I dont really get the difference:
VaadinServletService or VaadinPortletService described as low-level customization layer for processing requests.
VaadinSession of a UI with getSession() as lower-level session objects.
What is the difference and which one is to use when I want so store attributes during the whole UI independent user-session?
If in Vaadin 8, you have simple hierarchy of scope, on three levels.
ServletContextRepresents your entire Vaadin web app.
VaadinSessionRepresents each user's work session.
UIRepresents each web browser/tab within a session (Vaadin supports multi-window apps, pretty amazing).
The first is a standard part of every Java Servlet, defined in the spec.
The second is a wrapper around the session, also defined in the Java Servlet spec.
Vaadin is actually one huge Servlet, so it carries these features of context and session.
The UI class is unique to Vaadin. It represents the content of a web browser window/tab. Vaadin supports multi-window apps, tracking all the open windows/tabs as part of the session, a very nice feature of Vaadin.
To store state-wide app, use the standard ServletContext object. It carries a key-value collection known as "attributes". The key is of String type, and the value is of Object type. Call methods setAttribute, getAttribute, and removeAttribute. Use this collection for any objects you may need to access for any of your users, accoss their sessions. You may to learn about ServletContextListener by the way, to hook into your web app launching and exiting.
The VaadinSession class carries the same kind of key-value collection, with similar "attribute" methods. Use this to track items throughout the user’s work session, across them possibly opening/colsing multiple windows/tabs of your app. For example, in the session you would store the user’s Spirit Animal choice, their avatar image, and the fact that person has been authenticated via username/password credentials. See this page in the manual, Setting and reading session attributes.
If you want to store per-window settings, for something like their choice of background color or light/dark mode, store something on UI. Unfortunately, that class does not come with a convenient key-value store that I know of. So you'll need to add your own Map, or some other member variables to your UI subclass.
For more info, see my Answer to a similar Question. I made some nifty diagrams there. That question is about Vaadin 7, but as I vaguely recall, these concepts carry over between 7 and 8.
As for VaadinService and VaadinServletService, I have never understood exactly their role. They seem to represent various aspects of your entire Vaadin web at runtime. But neither carries a convenient key-value collection as like VaadinSession. (If you use Vaadin Flow, versions 10+, see VaadinContext, a class than does represent your entire web app, and does carry a convenient key-value collection of "attributes".)
My main goal is providing a search application written in jquery that is based on solr. (For those who unfamiliar with solr, just assume its a rest api that can return search result.)
For this goal I wrote many small applications and servlets that each one does an ad-hoc task.
For example:
SearchApp - a jquery app in which an end user can perform searches.
SolrProxy - A java servlet that plays a proxy role between the SearchApp and solr. One of the things it does is logging the user request for later analysis.
StatsApp- a servlet that performs analysis of the user activity and returns a json with the data.
Indexer - a java application that indexes data to solr according to my requirements. in this process it also fetches an SQLServer DB, and then performs some update commands to the DB.
IndexerServlet - an asynchronous servlet that uses Indexer to provide an ability to execute index by http request.
Nutch - an open source project that indexes data to solr for other requirements that are not accomplished in Indexer(3).
(MAYBE) - some service that will perform scheduled Nutch running.
And more components might be added.
It seems a bit wrong to have multiple java projects that each one does a single task, instead of having one project that handles most of the components.
Any ideas and insights on this?
Should I combine all the java apps to a single project? should I use some kind of a fremework for this? or should I live it as it is now?
I don't think it's a bad idea that you have all these separate applications. They all seem to be doing one thing, and doing it well. What you can do, is expose them via a unified interface. So essentially you have a facade that sits in front of all these disparate services that presents an abstract and uniform interface. The consumers of this service will have no idea what sits behind that facade. This is just as well, because now you can discretely update and replace individual components without affecting others. If you had combined all of them into one, you would have to push a new release every time you modified one of the components.
I'm going to write my first Java based web app, and I'm sort of lost how to begin.
Firstly, I would like a web app and a desktop app that do pretty much the same thing, without the hackish idea of embedding a web browser into the desktop app because that doesn't allow to easily make changes to the desktop without affecting the web app and vice versa.
Now, here my questions.
Right now, I have a bunch of POJOs and they communicate with a single class that, right now, uses a flat file as a "database", of course, in production, I would use a legitimate database and just change that single class. Is this a good idea? Will I be able to go from POJOs to a web app?
Should I use a framework? I would like to have this app written pretty soon, seeing that all the buisness logic is there, I just need to wrap it so its usable, so, I don't want to spend an extreme amount of time learning, say, Spring (which AFAIK is huge), but, I don't want to keep reinventing the wheel throughout my app either. I can always just use JSP and scriptlets...
If you said yes to the above, what framework(s) do you suggest? Please note that I would like a framework that I can start using in maybe 3-4 weeks of learning.
Will I have to start from scratch with the POJOs that I have written? They're well over 30k LOC, so, if it is like that, I'll be hesitant.
You will need:
a web framework. Since you have Swing background, JSF 2 will be your best bet (everything will be painful, of course, but JSF will get you up and going quickly and will help you avoid the most tragic mistakes). Also, wrapping business pojos into web guis is the main use-case for JSF and it's biggest focus.
a "glue framework". One thing that is much different with web applications as opposed to desktop ones is that you cannot create view components by yourself - they must be created when browser requests a page. So you have to find a way to create the view objects and deliver all the references to the pojos that represent logic, some of which may have very different lifecycles (this is not a problem on desktop, but on web you have to distinguish between pojos that live along with the whole application, along with a single user session, along with a single request, and so on).
The "glue framework" could also provide the additional benefit of managing transactions. You have three choices:
Spring. It's not half as complex as you thing; you only need to learn some basic stuff.
EJB. You would need a real application server, like Glassfish or JBoss
bare JSF has good support for dependency injection, the only drawback is the lack of automatic transaction management.
If I were in your position, I would go with bare JSF 2.0 - this way you only need to learn one new technology. At first, try to avoid libraries like PrimeFaces - they usually work worse than advertised.
edit - and addendum
or - what is "dependency injection"(abridged and simplified)
When request comes to a web application, a new task starts in a new thread (well, the thread is probably recycled, but that's not important).
The application has already been running for some time and most of the objects you are going to need are already built and should not get created again: you have your database connection pool, maybe some parts of business layer; it is also possible that the request is just one of many request made during one session, and you already have a bunch of POJOs that the user is working on. The question is - how to get references to those objects?
You could arrange your application so that resources are available through some static fields. They may be singletons themselves, or they could be acquired through a singleton locator. This tends to work, but is out of fashion (hard to test, hard to refactor, hard to reuse, lifecycles are hard coded in application). The real code could look like this:
public void doSomething() {
Customer Service cs = AppManager.getInstance().getCustomerService();
System.out.println(cs.getVersion());
}
if you need clustering and session management, you could build a special kind of broker that would know and provide to anyone all kinds of needed objects. Each type of object would be registered as a factory under a different name. This also works and is implemented in Java as JNDI. The actual client code would look like this:
public void doSomething() throws Exception {
CustomerService cs = (CustomerService)new InitialContext().lookup("some_fancy_looking_name_in_reality_just_string");
System.out.println(cs.getVersion());
}
The last way is the nicest. Since your initial object is not created by you but by the server just after http request arrives (details depend on the technology you choose, but your entry point might be a JSF managed bean or some kind of action controller), you can just advertise which references you need and let the server take care of finding them for you. This is called "Dependency Injection". Your acts as if everything is taken care of before your code is ever launched. Spring or EJB container, or CDI, or JSF take care of the rest. The code would look like this (just an example):
#EJB
CustomerService cs;
public void doSomething() {
System.out.println(cs.getVersion());
}
Note:
when you use DI, it really uses one of the two former methods under the hood. The good thing is: you do not have to know which one and in some cases you can even switch them without altering your code;
the exact means of registering components for injection differs from framework to framework. It might be a piece of Java code (like in Guice), an XML file (classic Spring) or an annotation (classic EJB 3). Most of the mentioned technologies support different kinds of configuration.
You should definitely use a framework as otherwise sooner or later you'll end up writing your own.
If you use maven then simply typing mvn archetype:generate will give you a huge list of frameworks to choose from and it'll set up all of the scaffolding for you so you can just play with a few frameworks until you find the one that works for you.
Spring has good documentation and is surprisingly easy to get started with. Don't be put off by the pages of documentation! You could use JPA to store stuff in the database. You should (in theory) just be able to annotate your existing POJO's to denote primary keys and so on and it should just work. You can also use JSP's within Spring if that makes life easier.
... I a bunch of POJOs and they communicate with a single class that, right now, uses a flat file as a "database", of course, in production, I would use a legitimate database and just change that single class. Is this a good idea? Will I be able to go from POJOs to a web app?
qualified yes. if the pojo's are sane you should not have many problems. many people use hiberbate.
Should I use a framework? I would like to have this app written pretty soon, seeing that all the buisness logic is there, I just need to wrap it so its usable, so, I don't want to spend an extreme amount of time learning, say, Spring (which AFAIK is huge), but, I don't want to keep reinventing the wheel throughout my app either. I can always just use JSP and scriptlets...
probably. spring is huge, but things like grails or roo can help.
if you want to have a responsive web app, you will need to do some kind of rich client (AJAX). this may require a lot of your code to run on the client. this means writing a lot of javascript or using gwt. this will be a pain. it probably will not be so easy to just "wrap it". if you have written a swing app, then basically that code will need to run on the client.
If you said yes to the above, what framework(s) do you suggest? Please note that I would like a framework that I can start using in maybe 3-4 weeks of learning.
i like groovy and grails - grails uses spring-mvc, spring, hibernate. but there is roo, play and others.
Will I have to start from scratch with the POJOs that I have written? They're well over 30k LOC, so, if it is like that, I'll be hesitant.
the code that will run on the server can probably be mostly left alone. the code that has to run on the client needs to be rewritten in javascript or maybe you can get some reuse out of that code by using gwt,
The Play Framework is doing great things. I would recommend it highly. Having worked with EJB apps and Tomcat/Servlet/Spring apps it's a breath of fresh air. After framework installation you get a working app in a few seconds. Reminds me of Ruby on Rails or Node.js with the type-safety of Java.
Much quicker turnaround on getting started, faster development cycles, and a clearer configuration model than previous Java web app frameworks.
http://www.playframework.com/
We have a gwt-client, which recieves quite a lot of data from our servers. Logically, i want to cache the data on the client side, sparing the server from unnecessary requests.
As of today i have let it up to my models to handle the caching of data, which doesn't scale very well. It's also become a problem since different developers in our team develop their own "caching" functionality, which floods the project with duplications.
I'm thinking about how one could implement a "single point of entry", that handles all the caching, leaving the models clueless about how the caching is handled.
Does anyone have any experience with client side caching in GWT? Is there a standard approach that can be implemented?
I suggest you look into gwt-presenter and the CachingDispatchAsync . It provides a single point of entry for executing remote commands and therefore a perfect opportunity for caching.
A recent blog post outlines a possible approach.
You might want to take a look at the Command Pattern; Ray Ryan held a talk at Google IO about best practices in GWT, here is a transcript: http://extgwt-mvp4g-gae.blogspot.com/2009/10/gwt-app-architecture-best-practices.html
He proposes the use of the Command Pattern using Action and Response/Result objects which are thrown in and out the service proxy. These are excellent objects to encapsulate any caching that you want to perform on the client.
Here's an excerpt: "I've got a nice unit of currency for implementing caching policies. May be whenever I see the same GET request twice, I'll cache away the response I got last time and just return that to myself immediately. Not bother with a server-side trip."
In a fairly large project, I took another direction. I developed a DtoCache object which essentially held a reference to each AsyncCallback that was expecting a response from a service call in a waiting queue. Once the DtoCache received the objects from the server, they were cached inside the DtoCache. The cached result was henceforth returned to all queued and newly created AsyncCallbacks for the same service call.
For an already-fully-built, very sophisticated caching engine for CRUD operations, consider Smart GWT. This example demonstrates the ability to do client-side operations adaptively (when the cache allows it) while still supporting paging for large datasets:
http://www.smartclient.com/smartgwt/showcase/#grid_adaptive_filter_featured_category
This behavior is exposed via the ResultSet class if you need to put your own widgets on top of it:
http://www.smartclient.com/smartgwtee/javadoc/com/smartgwt/client/data/ResultSet.html
There are two levels of caching:
Caching during one browser session.
Caching cross browser sessions, e.g the cached data should be available after browser restarted.
What to cache: depend on your application, you may want to cache
Protected data for particular user
Public static (or semi-static, e.g rarely to change) data
How to cache:
For the first caching level, we can use GWT code as suggested in the answers or write your own one.
For the second one, we must use Browser caching features. The standard approach is put your data inside html (whether static html files or dynamic generated by jsp/servlet for example). Your application then use http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsOverlay.html techniques to get the data.
I thought Itemscript was kind of neat. It's a RESTful JSON database that works on both the client (GWT) and server.
Check it out!
-JP