How to use Spring transactional management to update current user to database? - java

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)

Related

How to load global settings frequently used in application in Java

1) In my application we have a table which stores some settings detail which are used heavily for every functionality.Basically some conditions are set up in this table which are checked.
Now currently what we are doing is making DB call every now and then to fetch the details and check the condition.This has resulted in lot of DB calls and repetitive calls for the same condition.There are quite a lot of condition records in this table.We need to change this to make it perform better.
2) In my previous project also i had same requirement where we have a configuration table where such settings are configured,there we implemented it like load the configuration from table at start up of application and store them in System.setProperty(name,value)..and later use System.getProperty(name) to retrieve it.In case any settings is changed we update this in its System property.This worked like a charm.
However,in my current case(point 1 above) I don't think my prev way is best way to do it because lot of records present in the table having lot of columns.
Can anyone suggest a way how to achieve such kind of behavior in Java? Some of them I can think of is
1) Using System.setProperty like I explained.
2) Using caching like EHCache - standalone or with hibernate(as we are using hibernate).
Any better way to store such global settings of application so as to avoid DB calls?
Best way to do it using Ehcache(but I have never implemented it). And you should not play with System property it may cause conflict with other system properties.
How I did it in my case I have created a bean class which is having properties as yor table column like autoid, name, address, mobile.
public Map<Integer, PersonBean> getTag()
{
Map<Integer, PersonBean> map= new HashMap<Integer, PersonBean>();
Connection conn =getConnection();
Statement st=null;
ResultSet rs=null;
try
{
String sql = "select autoid,name, address, mobile from person";//person table
st = conn.createStatement();
rs = st.executeQuery(sql);
while(rs.next()){
int tagid=rs.getInt("autoid");
String name=rs.getString("name");
String address=rs.getString("address");
String mobile=rs.getString("mobile");
PersonBean tagdeatilbean= new PersonBean(auotoid,name, address, mobile);
map.put(rs.getInt("autoid"), tagdeatilbean);
}
return map;
}
catch (SQLException e) {
}
finally
{
}
}
and bean class
public class PersonBean
{
private int autoid;
private String name;
private String address;
private String mobile;
public PersonBean(int autoid, String name, String address, String mobile)
{
this.autoid=autoid;
.....
....
}
//setter
//getter
}
If this is web application then you can load this cache map in init method and call the value according to autuid of row from map.

java connection class, passing string from servlet

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.

Why does my JUnit test (that modifies a database entry) fail

EDIT: replaced 'retrieve.name == "name1"' by 'retrieve.name.equals("name1")'.
EDIT2: Added #BeforeClass and #AfterClass (credit: http://digitalsanctum.com/2012/06/01/play-framework-2-tutorial-ebean-orm/).
I'm writing JUnit tests for a play web app and for some odd reason I can't seem to modify the database entries. Here's the simplest example I could come up with that illustrates the problem:
#BeforeClass
public static void setup() throws IOException {
app = Helpers.fakeApplication(Helpers.inMemoryDatabase());
Helpers.start(app);
server = Ebean.getServer("default");
ServerConfig config = new ServerConfig();
config.setDebugSql(true);
ddl = new DdlGenerator((SpiEbeanServer) server, new H2Platform(), config);
// drop
String dropScript = ddl.generateDropDdl();
ddl.runScript(false, dropScript);
// create
String createScript = ddl.generateCreateDdl();
ddl.runScript(false, createScript);
}
#AfterClass
public static void stopApp() {
// drop
String dropScript = ddl.generateDropDdl();
ddl.runScript(false, dropScript);
Helpers.stop(app);
}
#Test
public void UserModify(){
// create user (User extends Model)
User user = new User();
user.id = (long) 1;
user.name = "name1";
user.save();
// modify
user.name = "name2";
user.update();
user.save();
// look-up
User retrieve = User.find.byId((long) 1);
assertFalse("Old name", retrieve.name.equals("name1"));
}
Needless to say this should pass, but it doesn't... I know you can use "update()" to change database fields, because someone else on the project says he uses it like that and it works.
Play Framework documentation: http://www.playframework.com/documentation/2.1.1/Home
Any ideas why this test fails?
This is happening because of a problem in Play Framework.
Play doesn't enhance code in "test" folder, only in "app" folder.
Because of that getters and setters are not generated, and Ebean is relying on setters to detect that object is dirty and to support lazy loading. This way in your case Ebean doesn't know that property was updated on object.
As a simple solution, you can create getters and setters yourself. Also, that seems to be fixed already and probably should be included in next Play release: https://github.com/playframework/Play20/blob/master/framework/test/integrationtest-java/test/models/EbeanEnhancementTest.java
Here's a simple Play project with User model and working test: https://github.com/pharod/so-play2-issue1
See more details on getters and setters generation by Play here, in "Caveats" section near bottom of page: http://www.playframework.com/documentation/2.1.1/JavaEbean
As others have stated, you should use .equals() for string equality.
But the main problem is that to run this kind of tests (accessing the database) You need a running application.
In play, this could be done, by running a fake application with the test. Check out this guide:
http://www.playframework.com/documentation/2.0/JavaTest

Managed bean not retaining input values and returning null after packaging in separate JAR

I have a very strange behavior in a managed-bean where it is not retaining the values sent from the jsf and when it s going to process the POST then the properties are all null.
The JSF I have is a simple form with 2 fields and a button, the values of the two fields are received, and the button executes a POST method to process the data received from the JSF. When running a debug, I can see that after pressing the button then the setter methods are executed with the values sent to the bean (good), but when it goes to execute the mothod then suddenly all properties are null.
I have to include, that all this was working fine before, it started with this behavior when I moved all the managed-beans (backbeans) to a separated JAR file. I know that if I move the files again to the webapp then it will work, but I am looking for a way to not accumulate too many files in the same project, it's taking too long for compilation and deployment.
Here is the code of the backbean and the JSF:
#Named
#RequestScoped
public class RegisterController implements Serializable {
private String accountType;
public String getAccountTypes() {
return accountType;
}
public void setAccountTypes(String accountType) {
this.accountType = accountType; // Here it stores the value ********
}
private String businessType;
public String getBusinessType() {
return businessType;
}
public void setBusinessType(String businessType) {
this.businessType = businessType; // Here it stores the other value *******
}
// Method called with the button
public String prepareCreate() {
if ("PERSONAL".equals(getAccountTypes())) // Here is null!! *************
{
return "PersonalSignup";
}
else
if (businessType == null) // Here is also null!! ************
{
JsfUtil.addErrorMessage(
new Exception(""), ResourceBundle.getBundle(CommonUtil.bundleStr).getString("cc.signup.accounttype.invalid.businesstype"));
}
...
Any help would be really appreciated, thanks.
Found the answer here: How does JSF find beans annotated with #ManagedBean?. Certainly if you need that your webapp looks into your jar file for managed-beans, only include a faces-config.xml file in your META-INF folder of your jar file.

Google App Engine datastore Entity not being deleted

I am using Google App Engine datastore to store 4 String values. The String vlaues are added to the datastore in a servlet:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity balances;
Key primaryKey;
String table = "MainTable";
String name = "Values";
primaryKey = KeyFactory.createKey(table, name);
Transaction t = datastore.beginTransaction();
// If the 'table' exists - delete it
datastore.delete(primaryKey);
// Really make sure it's deleted/
t.commit();
t = datastore.beginTransaction();
balances = new Entity("Balances", primaryKey);
updateBalances(balances);
datastore.put(balances);
// Save the new data
t.commit();
resp.sendRedirect("/balance.jsp");
I want to be able to update the four String values each time the servlet is run - which is why I look for the key first and delete it. I even use a separate transaction to ensure this really happens.
The key is found and is deleted and then the values are added. But when I load a .jsp file which retrieves the values the number of 'records' in the Entity grows by 1 each time. I do not understand why the record is not being deleted.
Here is the .jsp code:
<%
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Key guestbookKey = KeyFactory.createKey("MainTable", "Values");
Query query = new Query("Balances", guestbookKey);
List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
%>
<!-- This should always be 1, but it gorws each time the servlet is hit.-->
<%= greetings.size() %>
SOLUTION
I don't know what the problem was with the code in the original question. However I achieved my objective of persisting String values across sessions on a Google App Engine (GAE) by using a library called Objectify (http://code.google.com/p/objectify-appengine/) - which aims to simplify the use of the DataStore on GAE.
The library itself is just a .jar file and can be added to a Java project in Eclipse easily. I did not find using the library that easy to use...the main problem is registering the class which models the data you wish to save. Registration can only be done once!
To register the class only once I added a listener to my web app which registered the class with the Objectify framework and also created 4 random numbers and saved them:
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Register the Account class, only once!
ObjectifyService.register(Account.class);
Objectify ofy = ObjectifyService.begin();
Account balances = null;
// Create the values we wish to persist.
balances = new Account(randomNum(), randomNum(), randomNum(),
randomNum());
// Actually save the values.
ofy.put(balances);
assert balances.id != null; // id was autogenerated
}
public void contextDestroyed(ServletContextEvent event) {
// App Engine does not currently invoke this method.
}
private String randomNum() {
// Returns random number as a String
}
}
.. this code is run only once when the server starts - for this to happen I also needed to modify web.xml to add:
<listener>
<listener-class>.MyListener</listener-class>
</listener>
Then I just had a .jsp page which read the saved values:
<%
Objectify ofy = ObjectifyService.begin();
boolean data = false;
// The value "mykey" was hard coded into my Account class enter code here
// since I only wanted access to the same data every time.
Account a = ofy.get(Account.class, "mykey");
data = (null!=a);
%>
Here is my Account class:
import javax.persistence.*;
public class Account
{
#Id String id = "mykey";
public String balance1, balance2, balance3, balance4;
private Account() {}
public Account(String balance1, String balance2, String balance3, String balance4)
{
this.balance1 = balance1;
this.balance2 = balance2;
this.balance3 = balance3;
this.balance4 = balance4;
}
}
One last thing...I found the OBjectify documentation very helpful in understanding GAE Datastore irrespective of the Objectify framework
For future reference, I think your original example failed because of this line:
balances = new Entity("Balances", primaryKey);
This doesn't actually create an entity with primaryKey, but it creates an entity with primaryKey as the ancestor key. It will get an automatically generated id every time you store it.

Categories