Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

How to expand single user WebApp to multiple users

 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello folks, this might sound typical but it is true, I have been reading this forum a lot lately in my project and a lot of stuff has come from threads in this forum, I got to a point where I am stuck, I started a thread and then a bounty in "5t4ck0verfl0w" but I receive only one answer that just answered partially my predicament. Since the bounty is about to end I decided to ask in this forum, hopefully someone will point me into the right direction.


I am facing a situation where I have a WebApp hosted in RESIN (just like Tomcat I guess). So far I have been developing the app using db4o since I'm alone and I needed to complete the app ASAP, I have a DB for users and another DB for the application data for a single user (me). There is already a rudimentary session management that stores a Principal object that represents the user in the browser session. But I was wondering how can I expand it to multiple users/db.

I was thinking to expand the listener class that keeps the context data to pass the right db object to the app instance, or maybe set a filter for that purpose.

I have:

Context that holds a reference to some objects, one of those objects connects to a DB and checks for the user and password.

Presentation servlet (HttpServlet) mapped to "/" that has the login form that POST to /login.

Login servlet (HttpServlet) mapped to "/login" that checks the httpSession user password attributes against the respective object that rests in the Context, if there is a match sets an httpSession attribute that holds the user object and redirects the user to the app itself located at /index-debug.html if not it creates a new html page with a login form again.

Authorization and authentication filters mapped to /index-debug.html that verifies the httpServletRequest for the user id in the object attribute and checks whether or not the user has permission to access the app.

Finally a DB bean that is in charge of reading and writing to the webApp user data DB. When I execute certain method in the webApp CP2JAVAWS matches that method to the respective method in the bean, the problem is that this bean has a static database and so far it only allows one user at the time.

What I would like to do is somehow allow this DB bean to instantiate once per user and read and store the corresponding data depending of the current logged user. Or if it makes any sense read the user object attribute and use the corresponding database, schema or simply use the user id to store and read the data of the corresponding user. Since the DB access is abstracted in a separate Class I could go either way but, I have no clue of how to access attributes from the session.

Yes, a DB per user is discarded now, as a guy at "5t4ck0verfl0w" kindly explained the cons of a database per user.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not even a "Welcome to CodeRanch", this is just sad.
 
Bear Bibeault
Author and ninkuma
Marshal
Pie
Posts: 65335
97
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch!

You likely haven't receive any responses because it's hard to figure out what your question is. Your post is rather rambling and disjointed. Perhaps you could reply with a succinct summary of exactly what you are trying to find out.
 
Paul Clapham
Sheriff
Posts: 21567
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree with that guy who said don't have a database per user. So that means you should redesign your database so that it can hold data for more than one user. I expect that would involve adding user ID as a column to one or more tables -- I don't know anything about your database so that's all I can say about that.

And then you probably have numerous places in your application which incorporate the assumption that there's only one user. You'll have to track all of those down and fix them, it looks like your database access bean is going to be one of the culprits.

And really, you don't know how to access session attributes? You're going to have to brush up on your web programming then, as the session would be the ideal place to store the user ID.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you both for your answers and your attention. I apologize for my confusing post, I was trying to make it very simple and easy to read by not getting into too much detail but I guess it didn't turn up well.

So as I said my goal is to turn my single user webApp into a multiuser webApp. The client side webApp was developed using two key technologies, one is Cappuccino which is basically a compiler that translates Objective-J language (similar to Apple's Objective-C) into javascript and CP2JavaWS which is a a two part bridge written in Objective-J and Java. The Objective-J parts are some classes that I must include in the client code and the Java part is basically a filter and a listener.

Locally what I do is basically create an Objective-J class or classes interfaces that declares the same methods as a the beans on the in the server, then I create a connection (by means of CP2JavaWS object) to one of the filters that is mapped to an address path and I call the remote method as if it was local, then CP2JavaWS translates the call into JSON and send it to server. The filter in the server intercepts the httpServletRequest, analyze the JSON string, gets a Spring service factory from the servlet context, this factory then allocates an instance of a bean by calling getBean that matches the requested class, method and attributes from the intercepted httpServletRequest. Finally executes the method and returns to the client the method return value, again as JSON object.

There is already a primitive login authentication and authorization system and when the user logs in it does it by a an html form that POST to a servlet that checks the credentials and store a principal in the session.

There is a bean, is basically a POJO (sounds like chicken in spanish ;) ) that needs that session in order to access the right DB schema.

I have a basic knowledge on how to get a session or the HttpServletRequest from filters, servlets, and even beans but in this case it is not working since I think the bean wasn't instantiated by a jsp call but from a filter.

The only solution that comes to my mind is not pretty, is to pass the httpServletRequest or the session from the CP2JavaWS filter to the allocated bean but that will break the abstraction of CP2JavaWS.

The other idea doesn't have a knowledge foundation, I was imagining to somehow when I call the Spring context getBean method fake or pass the httpServletRequest to the Spring context so it thinks the bean allocation comes from a JSP request. That way I could call FacesContext and get the httpServletRequest or make the bean session aware or something more common.

I hope this new post makes more sense, I'm not a native english speaker.

 
Amit Ghorpade
Bartender
Posts: 2854
10
Fedora Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I am getting this right, the CP2JavaWS filter is just another filter which also instantiates the bean.
If the filter is able to put the bean into the session or even as in the request, you got your bean for the JSP.
Am I missing something?
 
Paul Clapham
Sheriff
Posts: 21567
33
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Samir Gartner wrote:... The client side webApp was developed using two key technologies...


Apart from all of the details which you provided, this small phrase suggests to me that somebody else developed the web application, and now you have inherited it. And you need to change it, but you don't really understand either the web application or how it works with those technologies. Am I right? (You do write English very well but perhaps, since your native language isn't English, I might have misinterpreted that phrase.)

At any rate, as I said earlier your first step is to understand how the web application works and how you can introduce a user ID into it. My feeling is that everything you have proposed so far is a wild guess at a quick fix, and I don't think it's going to work.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Forgive me if I didn't understand the comment but yes, the CP2JavaWS is just another filter and as such has access to the httpServlerRequest and session but it doesn't instantiates the bean itself, it calls the service factory object stored in the Spring context and this one instantiates it. The filter also executes the requested bean method, takes the result and transform it into JSON and returns it to the client as a httpServletResponse, but the goal is not to put the bean into the session object but to make the bean session aware, or somehow make it able to read the httpServletRequest (unless what you mean was actually that). I mentioned JSP because it is the usual way of calling beans but there are no JSP in my webApp.

I already tried to get the session trough FacesContext but the result is null. As I said I could just pass the HttpServletRequest object to the bean but it looks to me like it will be the final resort since I have read is not thread safe and I will be breaking the separation-independence (don't know the right word) of CP2JavaWS.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:
Samir Gartner wrote:... The client side webApp was developed using two key technologies...


Apart from all of the details which you provided, this small phrase suggests to me that somebody else developed the web application, and now you have inherited it. And you need to change it, but you don't really understand either the web application or how it works with those technologies. Am I right? (You do write English very well but perhaps, since your native language isn't English, I might have misinterpreted that phrase.)

At any rate, as I said earlier your first step is to understand how the web application works and how you can introduce a user ID into it. My feeling is that everything you have proposed so far is a wild guess at a quick fix, and I don't think it's going to work.


I actually developed the application since the beginning but not Cappuccino nor CP2JavaWS, although I started without knowing what I was getting my self into since all had done up to that moment was desktop programming not web programming. Cappuccino basically allowed me to develop a Web Application using almost the same knowledge and language of desktop programming and then I could just host the app online but it wasn't as easy as it sounded.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
now some some code, I try to simplify it:

this is my web.xml



the application context:



the CPWJavaWS filter



this is the Spring context listener:

 
Ulf Dittmer
Rancher
Posts: 42969
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would suggest that you leave all code aside for the moment, and come up with a proper design first. Which new DB fields do you need? When and how are those fields set, and which interaction might they have with other code? What additional steps would you need to take in the web app so that users are authenticated, and then only have access to heir own data? Until you have that, any code change is premature.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When I started the webApp I started working with DB4O, is a NOSQL OO DB, I used it because it is really simple to use and query but unfortunately it was designed for embedded applications. It is so simple that I decided to use two databases, one for users and another one for each user application data. It was the best choice back then because all of my friends quit as soon as we started and I had to show some results to access some government founds.

It is overkill, I know that now, specially for DB4O. On the other hand since the webApp was meant for holding some confidential information my logic back then was to have a DB per user per webApp so it seemed natural to continue to use DB4O and then I would migrate to postgresql. One more advantage of using DB4O at least at first is that if I have to change something in the database object model it is as simple as just change the object attributes and methods reset the data and start using it, it was a breeze since much of what I have done was trial and error (not the best way of doing things).

My goal is not to finish everything up by myself since I had to learn many subjects that the University didn't taught, I want to lay down the most critical parts and then get a new team (paid students) to improve everything.

My next goal after this is to work on an ER DB diagram and then refactor the Class in charge of interacting with the DB but since I will need to get a grip again on SQL (since we forced the University to fire the teacher because it was the worst teacher ever and we never learn about schemas) it will take some time away. Plus I know all of you help a lot in this forum with nothing but kind words as payment and I wanted to keep the problem as essential as possible.

There is already a registration and login mechanism, when the user logs in, I have a filter that sets a principal attribute on the session, what I want at first is to have access to that principal from the bean and create or load a db4o object with the user name, something like user1.db4o. In the future what I would like to do is to store in the Application Context a map that will link a sessionID with a user in the userDB, assign roles for each user, each role will be a match to a webApp and improve the authorization filter to check for those attributes. The filter is already in place but right now just allows everyone as long as they are registered.

I guess I will be fine with a user database and a database per application with a common userID column to match with the user database, is not like I'm trying to have 100 Web Applications.
 
Samir Gartner
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Someone gave me a hint that actually worked, although I need to test it more deeply. I have to use

and I did something like this:



then:



what do you guys think of this solution? I wish I didn't had to depend on Spring for this, but I looks like it will work.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic