I am developing a web application using JSP and Servlets.(Database: Oracle10, Container: Glassfish).
I have developed A Class for creating connection.
(Conn.java):
public class Conn
{
private Connection con = null;
public Connection getCon()
{
String home = System.getProperty("user.home");
home = home+"\\dbFile.properties";
//Read properties of Connection String from that file and Create Connection
return con;
}
}
Then I have a 4 other classes for SELECT, INSERT, UPDATE, DELETE transactions which are using above Conn.java class for getting connection:
(Select.java)
public class Select
{
private Conn connection = new Conn();
private Connection con = null;
private PreparedStatement pstmt = null;
private ResultSet rs=null;
public String[][] selectData(String query)
{
String[][] data=null;
if(con==null)
{
con = connection.getCon();
}
//execute query put data in two dimensional array and then return it
return data;
}
}
INSERT, UPDATE and DELETE are coded similar way as above Select.java is coded.
So in all servlets I am just using those 4(SELECT, INSERT, UPDATE, DELETE) classes, passing query to them and getting the result.
Sample Servlet
public class SampleServ extends HttpServlet
{
Select select = new Select();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String data[][];
data = select.selectData(QUERY_GOES_HERE);
//AND OTHER CODE
}
}
It works perfectly, but now our requirement is to change Database String after user is login. So I want to pass the User specific property file name to the Conn.java class. So for that I am storing the property file name in cookie.
I have think one way of doing this:
Get the cookie value in all servlets
Pass the cookie value to the selectData() method of Select.java class And from that class
pass the cookie value to the getConn() method of Conn.java class
So I want know if there is any better way to pass this Connection String file name to Conn.java class?
Thanks in advance.
HttpSession is where user info should be stored (with some concerns).
In your case, where you seem to have many different web applications, each of them will have a different session, and you will need to update all of them.
I prefer another approach (and this is a personal opinion, which can be discussed) which is based in the ThreadLocal class.
You can write a servlet filter, that will
read the cookie value
store it in a ThreadLocal
after the filter.doFilter method, you will have to clean it (This is extremely important, so you don't the have the chance of mixing sessions), just put the clean method in a finally block so it gets executed whatever happens.
The main advantage of this approach is that you may not have access to the HttpSession or HttpServletRequest, and you will still be able to get the value in the ThreadLocal.
An example of a ThreadLocal container you can use is this one :
public class ThreadLocalContainer {
private static ThreadLocal<String> userId=new ThreadLocal<String>();
public static String getUserId(){
return userId.get();
}
public static void setUserId(String uid){
userId.set(uid);
}
public static void resetUserId(){
userId.remove();
}
}
then you will be able to access the userId just by calling ThreadLocalContainer.getUserId() everywhere in your code, even if you don¡t have access to the http context.
Make sure you define the servlet filter in all your webapps, so the userId gets properly set.
Related
I am programming on a LoginForm with a MySQL database in Java. It all works well and now I wanted to add permissions. If someone logs in, the data from a specific user will be inserted in a Resultset. The problem is that I need to give the Resultset to the next class that I have the permissions in the other class and can say what the user is allowed to see. And the only clue I have is that if I call up the other class that I send it within it.
The Resultset
// That Code part is from Class A (In the Project LoginPage.java)
public void loginfunc() throws Exception {
String userID = userIDField.getText();
String password = String.valueOf((userPasswordField.getPassword()));
Connection con = getConnection();
try {
PreparedStatement statementuser = con.prepareStatement("SELECT * FROM uprtable WHERE username = '"+userID+"'");
//TODO transfer Resultset "result" to Class "WelcomePage"
ResultSet result = statementuser.executeQuery();
How I call up the other class
if (result.getString("username").equals(userID));
if (result.getString("password").equals(password)) {
frame.dispose();
String userresult = result.getString("username");
int rankresult = result.getInt("rank");
WelcomePage welcomePage = new WelcomePage(result);
}
The error I get is
'WelcomePage()' in 'com.company.WelcomePage' cannot be applied to
'(java.sql.ResultSet)'
From the error message it seems that WelcomePage class does not have a constructor that can accept a ResultSet.
You need to write a constructor in WelcomePage that can accept the ResultSet, the default constructor accepts no arguments.
For instance:
public class WelcomePage{
private ResultSet resultSet;
WelcomePage(ResultSet resultSet){
this.resultSet=resultSet;
}
}
PS: Τhis approach will work, but it would be better to parse the ResultSetinside the class that it was first referenced (Class A in this case), get all the required information release the database resources and then pass the needed data to the other class (Class B) in another way e.g. in a dedicated Java Bean.
For Example:
login user is [test2] and I want to update mAccount and mPassword.
How to get login session and click on the jsp form to update?
(mId is Primary Key)
What should I do?
When I click submit to update the SQL database, mAccount and mPassword are not updated.
I think my controller must have problem to get login session, so I can't update what I want. I click again and again but SQL database still not any change,controller not get test2 object to update.how to fix controller let me so confuse and anxious.this problem spent me 1week ...
SQL Member database:
Edit:
Was same image as above, likely missing the intended one
UpdateMemberController debug mode:
Bean:
private Integer mId;
private String mAccount;
private String mPassword;
private String mName;
private Date mDate;
private String mPhone;
private String mAddress;
private String mGender;
private String mEmail;
MemberDao:
public void setConnection(Connection conn);
public boolean checkAccount(String mAccount);
public int registerMember(MemberBean mb);
public MemberBean queryMember(String mAccount);
public MemberBean checkPassword(String mAccount, String mPassword);
public void updateMember(MemberBean mb);
DaoImpl:
#Override
public void updateMember(MemberBean mb) {
String hql = "UPDATE MemberBean mb SET mb.mAccount =:mAccount , mb.mPassword =:mPassword WHERE mId =:mId";
Session session = factory.getCurrentSession();
session.createQuery(hql).setParameter("mAccount", mb.getmAccount()).setParameter("mPassword", mb.getmPassword())
.setParameter("mId", mb.getmId()).executeUpdate();
}
MemberService:
boolean accountCheck(String mAccount);
int registerMember(MemberBean mb);
MemberBean queryMember(String mAccount);
public MemberBean checkPassword(String mAccount, String mPassword);
void updateMember(MemberBean mb );
MemberSeriveImpl:
#Transactional
#Override
public void updateMember(MemberBean mb) {
if (mb.getmAccount() != null && mb.getmPassword() != null) {
dao.updateMember(mb);
}
}
There is nothing bigger challenge for a developer if he get hold on debugging skills. If anything causing problem to developer he should hold the neck of that and solve it.
Check hibernate.properties for which database you have connected. If you connected to different database, update may be happening there.
(If step1 has no problem)
Directly jump to debug your dao implementation.(updateMember() method)
Confirm updateMember method is getting invoked or not.(Just put print statement)
First you print mAccount, mPassword and mId
If printed correctly, then put create query and execute update in try catch block and don't forget to print in catch block.
If exception not caught then print the executeUpdate return type.
If executeUpdate is zero then go to step 3.
Step 3: Why it is not updating to database. Am i committing transactions?
If i am relied on spring to manage transactions (begin, commit/rollback) then question yourself am i configured it correctly?
(Even i have not worked on Transaction in spring let me guess your problem)
Is spring container picking up service method with #Transactional?
What is your component scan base package? what is the package name of your service?
Is your service class scanned for components?
Note:
Add necessary information in your question
Add servlet-context.xml(in xml configuration) or equivalent java configuration file
Add root-context.xml (in xml configuration) or equivalent java configuration file
Filter question or remove unnecessary information
Bean(required)
MemberDao(required)
MemberService(required)
MemberSeriveImpl(required)
controller(Not required)
jsp(not required)
For university, it is my excercise to develop a multiplayer game with Java. The communication between the clients shall not be handled with sockets or the like, but with the help of a MySQL database where the clients are adding their steps in the game. Because it is a game of dice, not a lot of queries are needed. (approximiately 30 queries per gaming session are needed).
I never used MySQL in connection with Java before, so this maybe is a beginner's fault. But actually, I often get an exception during the execution of my java project.
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: User my_username already has more than 'max_user_connections' active connections
My queries are executed in a DatabaseHelper.java class. The results are returned and evaluated in another class of the project. Since I use an MVC pattern, I evaluate the results in a controller or model class.
This for example is one of my quers in the DatabaseHelper.java class. The other queries are similar:
private static Connection conn;
private Connection getConn() {
return conn;
}
public void db_connect() throws ClassNotFoundException, SQLException{
// JDBC Klassen laden
Class.forName(dbClassName);
// Verbindungsversuch auf 5 Sekunden setzen
DriverManager.setLoginTimeout(5);
this.setConn(DriverManager.getConnection(CONNECTION,p)); // p contains the username and the database
}
public void db_close(){
try {
this.getConn().close();
} catch (SQLException e) {
if(GLOBALVARS.DEBUG)
e.printStackTrace();
}
}
public String[] query_myHighscores(int gameid, PlayerModel p) throws SQLException{
List<String> rowValues = new ArrayList<String>();
PreparedStatement stmnt;
if(gameid == GLOBALVARS.DRAGRACE)
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score ASC LIMIT 0,3");
else
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score DESC LIMIT 0,3");
stmnt.setInt(1, gameid);
stmnt.setString(2, p.getUname());
ResultSet rs = stmnt.executeQuery();
rs.beforeFirst();
while(rs.next()){
rowValues.add(rs.getString(1));
}
stmnt.close();
rs.close();
return (String[])rowValues.toArray(new String[rowValues.size()]);
}
The CONNECTION string is a string which looks like jdbc:mysql://my_server/my_database
In the HighscoreGUI.java class, I request the data like this:
private void actualizeHighscores(){
DatabaseHelper db = new DatabaseHelper();
try{
db.db_connect();
String[] myScoreDragrace = db.query_myHighscores(GLOBALVARS.GAME1); // id of the game as parameter
// using the string
} finally {
db.db_close();
}
So I tried:
Closing the statement and the ResultSet after each query
Used db_close() to close the connection to the dabase in the finally-block
Never returning a ResultSet (found out this may become a performance leak)
The stacktrace leads in the DatabaseHelper.java class to the line
this.setConn(DriverManager.getConnection(CONNECTION,p));
But I cannot find my mistake why I still get this exception.
I cannot change every settings for the database since this is a shared host. So I'd prefer a solution on Java side.
The problem is that you exceed your allowed set of connections to that database. Most likely this limit is exactly or very close to "1". So as soon as you request your second connection your program crashes.
You can solve this by using a connection pooling system like commons-dbcp.
That is the recommended way of doing it and the other solution below is only if you may not use external resources.
If you are prohibited in the external code that you might use with your solution you can do this:
Create a "Database" class. This class and only this class ever connects to the DB and it does so only once per program run. You set it up, it connects to the database and then all the queries are created and run through this class, in Java we call this construct a "singleton". It usually has a private constructor and a public static method that returns the one and only instance of itself. You keep this connection up through the entire livetime of your program and only reactivate it if it gets stall. Basically you implement a "Connection Pool" for the specific case of the pool size "1".
public class Database {
private static final Database INSTANCE = new Database();
private Database() {}
public static Database getInstance() {
return INSTANCE;
}
// add your methods here.
}
When the program terminates, close the Connection (using a shutdown hook).
I am developing a java web service as well as a java client for the service and I am wondering if my design is even possible within the constraints of a SOAP-based, document style web service. On the server side I have a database which I am using a utility class to connect to and a couple other database "handler" classes that manipulate the database. My web service has WebMethods that return the handler classes. Each of the handler classes is annotated with the #XmlType annotation so that they can be bound to XML types. My question is if my client calls one of the webmethods and gets one of the database handler can I in turn manipulate the database on the server side through the methods of the handler (which are not annotated #WebMethod). Is something like this possible with SOAP-based web services?
I have example code below.
Here is the functionality of my utility class.
public class DBUtil {
public static getConnection() {
return DriverManager.getConnection(url, username, password);
}
}
Here is an example of one of my database handlers.
#XmlType
public class Handler1 {
public LinkedList<String> listDatabases() {
Connection con = DBUtil.getConnection();
LinkedList<String> list = new LinkedList<String>();
//use con to query database and fill list with know database names
return list;
}
public LinkedList<UserData> listUser(String database) {
//UserData is a user defined type that store information about user names
//and their privileges
Connection con = DBUtil.getConnection();
//query database and fill a LinkedList list with one UserData object
//for each database user
return list;
}
}
My other handler classes contain similar methods for querying and modifying tables.
Below is my web service.
#WebService()
#SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public class WSDatabaseImp implements WSDatabase {
//WSDatabase is my SEI
public WSDatabaseImp() {}
#WebMethod
public Handler1 getHandler1() {
return new Handler1();
}
//more get HandlerX methods
}
What I want to do is use Handler1 and such in my client to manipulate the database. The code below demonstrates what I want to do and assumes that I have run run wsimport that generate the artifacts.
public class Client {
public static void main(String[] args) {
WSDatabaseImpService service = new WSDatabaseImpService();
WSDatabaseImp port = service.getWSDatabaseImpPort();
Handler1 h = service.getHandler1();
LinkedList<String> list = h.listDatabases();
for(String s: list)
System.out.println(s);
}
}
Is this design possible? Thank you so much for your help.
First i show you the code then asked few questions. i have a class database connectivity like this (please ignore syntax error if any)
class DatabaseConnection {
private static Connection connection = null;
private static String driverName="";
private static String userName="";
private static String passwrod="";
private static String url="";
private DatabaseConnection() { }
public static void createConnection() {
if ( connection == null ) {
// read database credentials from xml file and set values of driverName, userName, passowrd and url
//create connection with database and set store this connection in connection object created a class level.
}
}
public static void closeConnection1() throws Exception{
if ( connection != null ) {
connection.close();
connection == null
}
}
public static void closeConnection2() throws Exception{
if ( connection != null ) {
connection.close();
}
}
public void insertData(Object data) {
// insetData in database
}
}
I want to know which close connection is more optimize in database connection. Lets suppose I have test class like this
class Test {
public static void main(String args[]) {
DatabaseConnection.createConnection();
DatabaseConnection.insertData(data);
DatabaseConnection.closeConnection2(); // we call also called close connection method within the insertData method after inserting the data
}
}
After creating database connection i insert data in database and then close the connection using closeConnection2 method. in this way connection has been close so if i want to insert some more method then i have to recreate connection with the database but i can't do this because connection object is not null and createConnection didn't execute the code inside the if statement. Now if I called closeConnection1 method for closing connection then in doing this i have to parse xml file again for credential which is not a optimize solution. can you tell me which method is good and if both are worse then please tell me more efficient way for creating and closing database connection.
I see two major problems with this:
The fact that everything (including the Connection object) is static means that you can't ever use this class from more than one thread at once.
parsing the configuration data and opening the connection are separate concerns and should not be mixed. At least move them into separate methods, the configuration could probably even go in another class.
The second thing alone will avoid having to parse the connection information multiple times.
An even better approach would be to use a DataSource instead of opening the connections each time. And then use a DataSource that's actually a connection pool!