I'm creating a program that uses several different interacting menus to allow the user to access different parts of the system. I'm using Netbeans to help with the coding.
At the moment I'm stuck on a task.
When a user logs into the system through a "login" form, the system validates the details, and that user is redirected to either a "user_details" or an "admin_menu" depending on the credentials. That much works fine. From there, the user is able to access a form that allows them to update their details which are already saved in the database.
The only way I've found to limit the simple user to update their details is to ask them to login again, and from there retrieve their details so that they can be updated. This process is messy, but it works.
with that in mind how do i retrieve whatever was imputed in the textfield "Username" that is located in the jform Login from another jform (User_details), the User_details jform only opens once the login is successful (once that occurs login is discarded and user_details is opened).
by the way i've done a lot of research but cant seem to find an answer to my problem.
here is part of my log in code :
String sql = "select * from user where Username =? and password=?";
try {
pst = con.prepareStatement(sql);
pst.setString(1, username.getText());
pst.setString(2, password.getText());
rs = pst.executeQuery();
int count = 0;
while (rs.next()) {
count = count + 1;
}
if (count == 1) {
JOptionPane.showMessageDialog(null, "Access Granted");
if ("manager#manage.com".equals(t.getText())) {
rs.close();
pst.close();
close();
Admin_menu am = new Admin_menu();
am.setVisible(true);
} else {
rs.close();
pst.close();
close();
User_details M = new User_details();
M.setVisible(true);
}
} else {
JOptionPane.showMessageDialog(null, "Incorrect Username or Password");
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
} finally {
try {
rs.close();
pst.close();
} catch (Exception ex) {
}
}
how can i make the User_details Jform get what ever was imputed in the textfield username?
You will probably want to create some class which represents the state of everything a logged in user does in your application. Traditionally, you would call it a Session. The logged in user is a property of that session, so you keep it in a field there. You pass the session into every frame you make, so that they all have access to it.
The session becomes invalid when the user logs out.
Then from your frames, components, whatever, you can get the current user from the session.
But please, try to separate front-end from back-end code here. Look into the MVC pattern.
try to declare the variables public and initiailize them with the other jframes where you want to use them for example
public your class{
initComponents();
String a;
}
hope this helps :)
You could create a class "BasicView" in wich a class variable exists where you store your information, so every instance of this class can use ist. Then you just need to extend this basic class, or just use BasicView.value or BasicView.getValue().
Also you can use a synchronized method to change this var.
public class BasicView {
private static Object value;
public synchronized void setValue(Object value) {
this.value = value;
}
public Oject getValue() {
return value;
}
.
.
.
}
I use this to init an ServicesLocator to get servies in all my beans. :)
EDIT: Also take a look at the MVC pattern and use this in the controller (Basic Controller) or something like that.
1. Use Composition, and also make sure that your GUI class always returns the same Object when referenced from different JFrames.
2. This can be achieved using Singleton Principle.
Create a class called session like this:
public class Session {
public static String userName = "";
}
When login happens set the value of Session.userName to the given userName and when the user logs out set Session.userName to "". You can access Session.userName simply by typing Session.userName. Other session variables should be defined in the Session class too.
Related
I'm new to Programming and Java and building a small Application in JAVA with SQL and UI(Jframes)
In the log-in frame after the user enters his user name and password I do a SQL select query to search USER table for this user. If the query returns 1 single row, the login button event handler triggers and the object of the next frame is created.
few frames later I have an SQL insert activity where I also have to insert the USER_ID of the person initiating the insert(the current logged in user).
What is the best practice to pass this information across a series of frame classes?
My initial idea is to pass the user_id as a parameter in the object so it gets set in the constructor of each frame class. but the problem is not all my frames really need this data. Only the final frame involved with the insertion needs the user ID. but in-order to get to that frame I have to pass through all other frames.
This doesn't seem like a good practice.
First Approach
The first possibility I thought of was to use java.util.Properties to store the application state inside of a properties file. The approach would be to use a singleton wrapper, let's say ApplicationState for reading/writing to properties file. This singleton class would be reachable from all frames, alternatively an instance of this class could be passed inside of constructor.
public class ApplicationState {
private static ApplicationState instance = new ApplicationState();
private ApplicationState() { }
public static ApplicationState getInstance( ) { return instance; }
public String read(String key) throws IOException {
try (InputStream input = new FileInputStream("path/to/config.properties")) {
Properties prop = new Properties();
prop.load(input);
return prop.getProperty(key);
}
}
...
}
Second Approach
Then I realized that a much cleaner solution would be to use the java.util.prefs.Preferences API. See Preferences API for details.
class A {
public void login() {
Preferences prefs = Preferences.userNodeForPackage(com.mycompany.MyClass.class);
prefs.putInt("userId", 11);
...
}
}
class B {
public void insert() {
Preferences prefs = Preferences.userNodeForPackage(com.mycompany.MyClass.class);
int userId = prefs.getInt("userId", 0); // 0 is default identifier
...
}
}
In addition because you want to store sensitive information, encrypted storage would be useful. For using encrypted preferences see this article.
So I have the first steps of a webapp, have class Doctor and I want to perform some operations like view all, insert, delete, etc. :
public class Doctor {
public String firstName;
public String lastName;
public int id;
public Doctor(){
}
public Doctor(int id, String first, String last){
setId(id);
setFirstName(first);
setLastName(last);
}
// getters and setters
Here is an implementation of one method from my interface Service. They are all pretty much the same with the appropriate sql queries. I tried following several different tutorials.
public class DAOImpl implements DAO{
public void insertUpdateDoctor(Doctor doctor){
String sql = "INSERT INTO doc_flight.docflight_doctors(id, first_name,last_name)" + "Values(?,?,?)";
jdbcTemplateObject.update(sql,new Object[]{doctor.getId(),doctor.getFirstName(),doctor.getLastName()});
Heres the part in main where I try to call it. The program doesn't even try to enter the method, it doesn't come up in debug and moves to the next method I try in main, view all, which works. Presumably, I'm not calling the method correctly and tried rewriting all parts several times. Help?!
Doctor test = new Doctor(17,"jack", "sparrow");
service.insertUpdateDoctor(test);
The issue itself it's not pretty clear for me.
If the problem is that when calling this:
Doctor test = new Doctor(17,"jack", "sparrow");
service.insertUpdateDoctor(test);
The runtime is not getting inside insertUpdateDoctor, just check how you are instantiating the object service
if the problem is that it's not executing correctly the sql statement, try by using a PreparedStatement (it's a good practice) by doing something like:
String connectionStr = StringUtils.format("INSERT INTO %s.docflight_doctors(id, first_name,last_name) Values(?,?,?)", this.databaseName);
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(connectionStr)) {
preparedStatement.setInt(1, doctor.getId());
preparedStatement.setString(2, doctor.getFirstName());
preparedStatement.setString(3, doctor.getLastName());
preparedStatement.execute();
connection.commit();
} catch (Exception ex) {
this.logger.error(String.format("Error when inserting: %s", ex.toString()));
}
Hope it may help you.
For me I would not write this class from scratch, I would prefer to generate it in few clicks and save my time using The Cloud Wizard:
Go to https://codegen.cloud-wizard.com
Click on Java
From the technologies section press on Java SE
Select JDBC Class transformer.
In the metadata section enter a name for the JDBC Class e.g. (DoctorDao)
Add some fields e.g. first name and last name
Press on generate code and you will get your class ready and working as expected.
I need to use a servlet to validate login/password. That's fine already.
I have a method in a DAO class that returns a resultSet list of values through a prepareStatement.
I'm using a query that brings this filtered result with a where clause (by user's name).
The problem is: how can I get the servlet parameter (name of the user who logged in) and set it on the prepareStatement ?
The code follows:
public class DaoPojoJoin extends Dao {
public List<PojoJoin> listUserDegrees() {
List<PojoJoin> dg = new ArrayList<PojoJoin>();
if (openConnection()) {
try {
st = cn.prepareStatement("SELECT USER, MATTER, DEGREE FROM DEGREES x "
+ "right outer join USERS y on x.idUser=y.idUser "
+ "right outer join MATTER z on idMatter=z.idMatter "
+ "where x.iduser=?"); // filter result by user's name
// How can I have something like this:
// st.setString(1,usr.request.getParameter("user"));
// or this:
// st.setString(1,.getAttribute(user));
rs = st.executeQuery();
while (rs.next()) {
PojoJoin pj = new PojoJoin();
rs.getString("USER");
rs.getString("MATTER");
rs.getDouble("DEGREE");
pj.setUsuario(rs.getString("USER"));
pj.setDisciplina(rs.getString("MATTER"));
pj.setNota(rs.getDouble("DEGREE"));
nota.add(pj);
}
} catch (Exception ex) {
err = ex.getMessage();
} finally {
closeConnection();
}
}
return dg;
}
}
Thanks in advance.
Ask for it as method argument. The DAO should not care about the context it is sitting in and is supposed to be reuseable everywhere else (e.g. a plain vanilla Java Application which doesn't use servlets).
Thus so
public List<PojoJoin> listUserDegrees(String username) {
// ...
}
or
public List<PojoJoin> listUserDegrees(Long userId) {
// ...
}
or
public List<PojoJoin> listUserDegrees(User user) {
// ...
}
Finally just let the caller (the servlet) pass it in.
Unrelated to the concrete problem, your DB resource handling doesn't seem to be threadsafe. I'd work on that to avoid serious problems whenever your webapp starts to be used by multiple users.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Before i go any further it would be nice to know if there is any major design flaws in my program so far. Is there anything worth changing before i continue?
Model
package model;
import java.sql.*;
import java.util.*;
public class MovieDatabase {
#SuppressWarnings({ "rawtypes", "unchecked" })
public List queryMovies() throws SQLException {
Connection connection = null;
java.sql.Statement statement = null;
ResultSet rs = null;
List results = new ArrayList();
try {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
statement = connection.createStatement();
String query = "SELECT * FROM movie";
rs = statement.executeQuery(query);
while(rs.next()) {
MovieBean bean = new MovieBean();
bean.setMovieId(rs.getInt(1));
bean.setTitle(rs.getString(2));
bean.setYear(rs.getInt(3));
bean.setRating(rs.getInt(4));
results.add(bean);
}
} catch(SQLException e) {
}
return results;
}
}
Servlet
public class Service extends HttpServlet {
#SuppressWarnings("rawtypes")
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Movies!");
MovieDatabase movies = new MovieDatabase();
try {
List results = movies.queryMovies();
Iterator it = results.iterator();
while(it.hasNext()) {
MovieBean movie = new MovieBean();
movie = (MovieBean)it.next();
out.println(movie.getYear());
}
}
catch(SQLException e) {
}
}
}
Bean
package model;
#SuppressWarnings("serial")
public class MovieBean implements java.io.Serializable {
protected int movieid;
protected int rating;
protected int year;
protected String title;
public MovieBean() {
}
public void setMovieId(int movieidVal) {
movieid = movieidVal;
}
public void setRating(int ratingVal) {
rating = ratingVal;
}
public void setYear(int yearVal) {
year = yearVal;
}
public void setTitle(String titleVal) {
title = titleVal;
}
public int getMovieId() {
return movieid;
}
public int getRating() {
return rating;
}
public int getYear() {
return year;
}
public String getTitle() {
return title;
}
}
Here are a couple of suggestions:
Your MovieDatabase has the Connection creation embedded inside it. You don't use a Connection pool that way.
You embed the connection parameters (e.g., driver class, URL, etc.) inside your code. Best to externalize them.
You don't clean up any JDBC resources. This is guaranteed to bring you grief.
You have empty catch blocks. This is a heinous error. Log the stack trace. You'll have no way of knowing if anything is wrong as coded.
MovieBean? Names matter - make it Movie.
Your default constructor does nothing at all, and it's the only constructor you provide. Your String reference to title will be null. I think you should have one constructor that initializes all the fields properly.
Your Service should not extend Servlet. I think you should have a POJO interface and an implementation that has nothing to do with HTTP. You can't use this service (or test it) without the web.
Another empty catch block - you're asking for trouble. When will you learn to print the stack trace?
I wouldn't have a MovieDatabase; I'd go with a MovieDao interface that had CRUD operations, like this:
package persistence;
public interface MovieDao
{
List<Movie> find();
Movie find(int id);
List<Movie> find(String title);
void save(Movie movie);
void update(Movie movie);
void delete(Movie movie);
}
Much of the following is style, not necessarily the 'right' way, and certainly not the only way.
I'd move the database connection
to a try block in the servlet's #doGet. I'd pass the
connection to
MovieDatabase#queryMovies. The
reason is, what happens if in that same request you need
to do another query using another
class? Your connection is in
MovieDatabase and another class
would have no access to it. If you had a situation where both classes could update the database, you'd be unable to roll back the entire transaction. Not good.
I'd add a commit statement at the end of the 'success' path in #doGet
I'd add after try block containing the database connection an exception block, wherein I'd issue a rollback. So if there's an exception, a rollback would be performed every time.
I'd close the database connection in
#doGet's finally block. This is most important. edit - see the pseudocode below for an example
If you don't move the connection into the servlet, then straight
away you should close that
connection in #queryMovies' finally
clause.
If this were a larger project, I'd use Hibernate and its tools to
generate DAOs and models. Hibernate
would generate for you a class and
method that would return a
collection of MovieBeans to you.
You wouldn't have to do anything but
invoke it. Auto-generated database
access code is good.
I'd add a JSP and put the collection you're building into the request. Then your jsp could iterate over the collection and format it as appropriate. This moves the presentation of the information out of the servlet, which is a coordinator of action, not a formatter of data in the MVC model.
If you implemented the above suggestions, it would probably drop your number of lines of code by 50% or more. Learning Hibernate can be a headache, so it wouldn't necessarily be easier or faster the first time. The reason it reduces the lines of code (while doing pretty much the same work) is that generated code is pretty much right and coders don't have to worry about it.
I use the following pattern in my servlets all the time. This is pseudocode, not real java.
Connection conn = null;
try {
conn.getConnection(...);
// your implementation here
conn.commit();
} catch (Exception e) {
conn.rollback();
} finally {
conn.close();
}
The point is that the database connection can always be passed to workers, work is always committed unless something goes wrong. If something goes wrong, there's guaranteed to be a rollback. In either case, the database connection is closed when its all over.
It's pretty simple and straightforward, no big issues. The only thing I would point out is that you're doing a SELECT * then refer to the result set by column index. This is not a problem at this stage but if your schema changes (say, a field gets added in the middle) then your code will break. I would explicitly select the column names:
SELECT id, title, year, rating FROM movie
There are many things wrong (many have already pointed out most of them). Seems like the code is written in 90's. I strongly suggest you read about layered architecture, separation of concerns, MVC, DAO pattern. Then you will answer the question yourself and I will up vote your answer ;-).
I am using some third party library to connect to a server via async protocol and get response back. For example method to get userid by username looks like this:
public int getUserid(String username) {
int userid = 0;
connection.call("getUserid", new Responder() {
public void onResult(final int result) {
System.out.println("userid: " + result);
//how to assign received value to userid and return it?
}
}, username);
//wait for response
while (userid == 0) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
return userid;
}
The problem is I can't assign returned "result" from server response to "userid" variable from the method (in order to return it after). How to solve this? I probably can assign it to some class variable rather than method variable but I want to keep it within method scope so I don't have to deal with concurrency issues.
Thanks.
If I understand your question correctly, you're asking how you can write a variable from inside an anonymous class.
Anonymous classes can only access final variables, and can't directly "write" them.
A straightforward solution that is "good enough" is to create sort of a ValueBox class with a single value field and a getter and setter. You can then instantiate a new one in the function as a final variable, and have your anonymous class access it. The anonymous class will use its getter and setter to write/read.
The fact that the variable is final just means that you can't aim the reference anywhere else, but you can still change the contents of the referred object from either function.
The bigger problem you are going to have is in waiting until the callback has been called. This sort of wait-sleep might be good enough, but you may want to consider timeouts, threads, etc, depending on what you're trying to achieve.
In addition, this all assumes that you are never going to call this twice on the connection. Otherwise, you need to provide more info to us on your synchronization model.
Here's some sample code:
public int getUserid(String username) {
final ValueBox<Integer> userid = new ValueBox<Integer>();
connection.call("getUserid", new Responder() {
public void onResult(final int result) {
System.out.println("userid: " + result);
userId.setValue(result);
//how to assign received value to userid and return it?
}
}, username);
//wait for response
while (userid.isEmpty()) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
return userid.getValue();
}
The simplest change is to use something like java.util.concurrent.SynchronousQueue. But possibly you want to provide an event driven interface yourself.