I have the following code in UserController in my Session Scoped Bean
public void addItemToBundle(ItemEntity item){
//System.out.println(item.getTitle());
try {
em.getTransaction().begin();
UserEntity user = em.find(UserEntity.class, this.username);
BundleEntity bundle = new BundleEntity();
BundleEntityPK compositePk = new BundleEntityPK();
compositePk.setCheckedOutDate(new Date());
compositePk.setItemId(item.getItemId());
compositePk.setUsername(user.getUsername());
bundle.setId(compositePk);
Set<BundleEntity> bundles = new HashSet<BundleEntity>();
bundles.add(bundle);
user.setBundleEntities(bundles);
em.persist(user);
em.flush();
em.getTransaction().commit();
} finally {
}
}
public String addToBundle(){
try {
addItemToBundle(item);
} catch (NullPointerException e) {
e.getMessage();
}
return null;
}
This code uses private ItemEntity item; which gets passed in by the following JSF markup:
<p:commandLink action="#{itemController.item}">
<f:setPropertyActionListener target="#{itemController.selectedItem}" value="#{movie}" />
</p:commandLink>
(I'm using PrimeFaces in this example) The problem is that the addItemToBundle is not calling any SQL code in the console (I have FINE enabled) and the bundle never gets created or added to the user. I also tried em.persist(user) and em.flush() and setting cascadeType in my UserEntity with no luck.
#OneToMany(mappedBy="userEntity",cascade=CascadeType.PERSIST)
private Set<BundleEntity> bundleEntities;
Thanks!
You know that this:
try {
addItemToBundle(item);
} catch (NullPointerException e) {
e.getMessage();
}
is very bad practice, right? Maybe, that's the problem here, you run into a NPE and never notice it.
You should at least log the exception to know what's going on there (just for demo purposes, I've used stdout, please replace with your favorite logging framework):
try {
addItemToBundle(item);
} catch (NullPointerException e) {
System.err.println(e.getMessage()); //use logger here
}
Related
i am trying to persist multiple entities to database. but i need to roll back all inserts if one of them faces an exception. how can i do that?
here is what i did:
public class RoleCreationApplyService extends AbstractEntityProxy implements EntityProxy {
#Inject
#Override
public void setEntityManager(EntityManager em) {
super.entityManager = em;
}
#Resource
UserTransaction utx;
public Object acceptAppliedRole(String applyId, Role parentRole, SecurityContext securityContext) throws Exception {
utx.begin();
try {
FilterWrapper filter = FilterWrapper.createWrapperWithFilter("id", Filter.Operator._EQUAL, applyId);
RoleCreationApply roleCreationApply = (RoleCreationApply) getByFilter(RoleCreationApply.class, filter);
Role appliedRole = new Role();
appliedRole.setRoleUniqueName(roleCreationApply.getRoleName());
appliedRole.setRoleName(roleCreationApply.getRoleName());
appliedRole.setRoleDescription(roleCreationApply.getRoleDescription());
appliedRole.setRoleDisplayName(roleCreationApply.getRoleDisplayName());
appliedRole.setCreationTime(new Date());
appliedRole.setCreatedBy(securityContext.getUserPrincipal().getName());
Role childRole = (Role) save(appliedRole);
parentRole.setCreationTime(new Date());
parentRole.setCreatedBy(securityContext.getUserPrincipal().getName());
parentRole = (Role) save(parentRole);
RoleRelation roleRelation = new RoleRelation();
roleRelation.setParentRole(parentRole);
roleRelation.setChildRole(childRole);
RoleRelation savedRoleRelation = (RoleRelation) save(roleRelation);
PostRoleRelation postRoleRelation = new PostRoleRelation();
postRoleRelation.setPost(roleCreationApply.getPost());
postRoleRelation.setRoleRelation(savedRoleRelation);
ir.tamin.framework.domain.Resource result = save(postRoleRelation);
utx.commit();
return result;
} catch (Exception e) {
utx.rollback();
throw new Exception(e.getMessage());
}
}
}
and this is save method in AbstractEntityProxy class:
#Override
#ProxyMethod
public Resource save(Resource clientObject) throws ProxyProcessingException {
checkRelationShips((Entity) clientObject, Method.SAVE, OneToOne.class, ManyToOne.class);
try {
entityManager.persist(clientObject);
} catch (PersistenceException e) {
throw new ResourceAlreadyExistsException(e);
}
return clientObject;
}
but when an exception occures for example Unique Constraint Violated and it goes to catch block, when trying to execute utx.rollback() it complains transaction does not exist and so some entities will persist. but i want all to roll back if one fails.
PS: i don't want to use plain JDBC. what is JPA approach?
Have a list of data need to be saved. Before the save had to delete the existing data and save the new data.
If any of the delete & save is failed that transaction need to roll back, rest of the delete & save transaction should continue.
public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
LabResResponse labResResponse = new LabResResponse();
List<Long> relInvstid = new ArrayList<Long>();
try{
if(invstResults != null){
List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
for(LabResInvstResult dto: labResInvstResults){
if(dto != null){
//delete all child records before save.
deleteResult(dto, relInvstid);
}
}
}
labResResponse.setRelInvstids(relInvstid);
}catch(Exception e){
e.printStackTrace();
}
return labResResponse;
}
Here new transaction will added for each delete & save
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = { Exception.class })
private void deleteResult(LabResInvstResult dto, List<Long> relInvstid) {
try{
labResultRepo.deleteById(dto.getId());
LabResInvstResult result = labResultRepo.save(dto);
}catch(Exception e){
e.printStackTrace();
}
}
On delete it throws an exception "Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call"
I can solve this by adding a #Transactional for public LabResResponse saveLabResult(List invstResults) method.
But my intial usecase will not work this will roll back entire list of transaction.
Here are two problems.
The first problem is that you call the "real" deleteResult method of the class. When Spring sees #Transactional it creates a proxy object with transactional behavior. Unless you're using AspectJ it won't change the class itself but create a new one, proxy. So when you autowire this bean you will be able use proxy's method that runs transaction related logic. But in your case you're referencing to the method of the class, not proxy.
The second problem is that Spring (again if AspectJ is not used) can't proxy non-public methods.
Summary: make the deleteResult method public somehow and use proxied one. As a suggestion, use another component with deleteResult there.
You are catching exception out of for loop, while your requirement says you want to continue the loop for other objects in list.
Put your try/catch block with-in loop. It should work fine
public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
LabResResponse labResResponse = new LabResResponse();
List<Long> relInvstid = new ArrayList<Long>();
try{
if(invstResults != null){
List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
for(LabResInvstResult dto: labResInvstResults){
if(dto != null){
//delete all child records before save.
try {
deleteResult(dto, relInvstid);
} catch(Exception e){
e.printStackTrace();
}
}
}
}
labResResponse.setRelInvstids(relInvstid);
}catch(Exception e){
e.printStackTrace();
}
return labResResponse;
}
I'm attempting to launch an Edit Customer Window with text fields filled with reference from the rows of a table. The Table and Dialog both have different controller classes.
Here's the code snippet from the table in question that gives us the required customerID when a user double clicks on a row.
Table Controller: CustomersController:
#Override
public void initialize(URL location, ResourceBundle resources) {
populateCustomerTable();
tableListeners(null);
}
void tableListeners(CustomerData customerData){
tblcustomer.setRowFactory(tr -> {
TableRow<CustomerData> row = new TableRow<>();
row.setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (!row.isEmpty())) {
int selectedCustomerID = row.getItem().getCustomerID();
System.out.println("A certain row: " + selectedCustomerID + " has been clicked!");
Stage stage = new Stage();
FXMLLoader loader = new FXMLLoader();
try {
Parent root = loader.load(getClass().getResource("../view/popups/edit_customer.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("Editing Existing Customer's Details");
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(btnEditCustomer.getScene().getWindow());
stage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
});
return row;
});
}
I want selectedCustomerID from the above piece of code to be parsed into the EditCustomerController class hence when the dialog launches, it's text fields should be prepoulated with values suppled from the select query that queries the database with the where condition being tht selectedCustomerID from the CustomersController class.
Code snippet from EditCustomerController class:
#Override
public void initialize(URL location, ResourceBundle resources) {
//populateEditCustomerFields(1);
}
void populateEditCustomerFields(int customerID){
this.customer_ID=customerID;
System.out.println(customer_ID);
try {
con = DatabaseConnection.getConnected();
stmt = con.createStatement();
rs = con.createStatement().executeQuery("SELECT * FROM `h_customers` WHERE `customerID`=" + customer_ID);
while (rs.next()) {
title.setText(rs.getString("title"));
firstName.setText(rs.getString("firstName"));
lastName.setText(rs.getString("lastName"));
nationalID.setText(String.valueOf(rs.getInt("nationalID")));
//dob.setText(rs.getString("DOB"));
mobilePhone.setText(rs.getString("mobilePhone"));
workPhone.setText(rs.getString("workPhone"));
email.setText(rs.getString("email"));
}
} catch (SQLException ex) {
Logger.getLogger(NewRoomController.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
The Idea here is to parse selectedCustomerID from CustomersController into the initialize method of EditCustomerController so the Dialog can launch with the customer details that require editing. I've searched for solutions all over the web and here on StackOverflow, some come close to answering me, some are too complex for my newbie mind, but none has helped. Any solution would be highly appreciated. I will provide any further clarification required.
You can get the controller class and invoke its necessary methods. See this answer for getting controller, then do
editCustomerController.populateEditCustomerFields(selectedCustomerID);
on table row double click.
Further to improve performance, you can load the edit_customer.fxml only once and when the user double clicks, refresh its rendered data with editCustomerController.populateEditCustomerFields(selectedCustomerID).
I'm trying to create a simple DB connection using JPA.
It works fine but when I try to Throw an Exception to the client I get the error:
[ERROR] [browsereditor] - Line 210: No source code is available for type javax.persistence.EntityExistsException; did you forget to inherit a required module?
[ERROR] [browsereditor] - Line 212: No source code is available for type javax.persistence.EntityNotFoundException; did you forget to inherit a required module?
I get no error in development mode and it compiles fine, but when the app module is loaded there is where I get the error.
I have the required imports in server/Composer and client/Presenter classes
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
I also added the following jars to the classpath and build path:
javax.persistence.jar
jpa-annotations-source.jar (http://code.google.com/p/google-web-toolkit/issues/detail?id=1830#c14)
I also tried adding to gwt.xml
<source path='client'/>
<source path='shared'/>
<source path='server'/>
Any ideas on how to tell eclipse where to find the source code??
Thanks
Here is the code:
//Create composer from Composer.class in server
public static Composer createComposer(String name)
throws EntityExistsException {
Composer comp = new Composer();
comp.setName(name);
comp.setId(1);
EntityManager entityManager = entityManager();
entityManager.getTransaction().begin();
entityManager.persist(comp);
entityManager.getTransaction().commit();
entityManager.close();
return comp;
}
///fire Request from createComposer(above) in Presenter.class
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerProxy comp;
comp = arg0;
}
public void onFailure(Throwable caught)
throws Throwable {
// Convenient way to find out which exception
// was thrown.
try {
throw caught;
} catch (EntityExistsException e) {
} catch (EntityNotFoundException e) {
}
}});
}});
[ERROR] [browsereditor] - Line 210: No source code is available for type javax.persistence.EntityExistsException; did you forget to inherit a required module?
[ERROR] [browsereditor] - Line 212: No source code is available for type javax.persistence.EntityNotFoundException; did you forget to inherit a required module?
You can't use types such as EntityExistsException or EntityNotFoundException in client-side GWT code at all.
These are plain Java classes and GWT don't know how to translate them to JavaScript.
You can only use very limited part of external libraries in your client-side code. These libraries (like Visualisation for example) are designed and prepared specifically for client-side and require inheriting their GWT module in your application's module.
I think that what you really want to do is something like that:
public void onFailure(ServerFailure failure) throws Throwable {
if(failure.getExceptionType().equals("javax.persistence.EntityExistsException")){
...
}else if(failure.getExceptionType().equals("javax.persistence.EntityNotFoundException")){
...
}
}
Because you can read type of server-side exception as String, see Javadoc for Receiver and ServerFailure.
Thanks Piotr for your help.
Here is the code for what I finally did:
Code in the client
req.fire(new Receiver<ComposerProxy>() {
public void onSuccess(ComposerProxy arg0) {
ComposerProxy comp;
comp = arg0;
}
public void onFailure(ServerFailure failure) {
serverError.getServerError(failure,
"onAddButtonClicked");
}
});
I created a class to handle the errors
public class ServerError {
public ServerError() {
}
public void getServerError(ServerFailure failure, String message) {
// Duplicate Key Error
if (failure.getMessage().contains(
"IntegrityConstraintViolationException")) {
Window.alert("Duplicate Key " + message);
return;
}
// Connection Error
if (failure.getMessage().contains("NonTransientConnectionException")) {
Window.alert("Connection error ");
return;
}
// TimeOut Error
if (failure.getMessage().contains("TimeoutException")) {
Window.alert("Timeout Error" + message);
return;
}
// Other Error
else {
Window.alert("Duplicate Key " + message);
return;
}
}
}
Service in the server
public static Composer createComposer(String name) throws Throwable {
EntityManager entityManager = entityManager();
Composer comp = new Composer();
try {
comp.setName(name);
comp.setId(1);
entityManager.getTransaction().begin();
entityManager.persist(comp);
entityManager.getTransaction().commit();
} catch (Exception e) {
log.error("Error in Composer::createComposer( " + name + ") //"
+ e.toString());
throw e;
} finally {
entityManager.close();
}
return comp;
}
One problem I found is that the variable 'ServerFailure failure'only contains info in the failure.message; all the other variables are null.
Can anyone please suggest a website where I can find step by step instructions on how to add jdbc to a gwt project and how to access data from a database within a gwt project? I'm new to GWT and can't to find any good resources to learn from.
Thanks
GWT is a client side technology - it creates code that runs on a browser. You can not talk to databases directly from browser. You need an intermediary servlet server. Here is what you need to do:
Use GWT-RPC for your GWT code to talk to the servlet server. There are a lot of good tutorials around the web.
Create server-side code that uses JDBC to talk to your database. Ankit already provided you with a link to example: http://code.google.com/p/gwt-examples/wiki/project_MySQLConn
You can also take a direct route and use one of the pre-packaged frameworks that allow you to talk "directly" from GWT to database, where framework provides the intermediate step (GWT-RPC to JDBC): gwtexpress
Just follow the google's tutorial itself. GWT is a java framework which converts java code into javascript code on compilation. And please dont confuse with database connection and gwt application. They are totally independent. In gwt application you will be seeing client & server packages. Only classes inside client package will be compiled to javascript code. You have to write jdbc code inside the server package. These codes will not be (can't be) compiled into javascript.
To bring the database data into client side you have to make rpc call.
I hope this information helps you for your basic understanding.
In that code you can learn how to connect database in gwt with jdbc
public class ExampleServiceImpl extends RemoteServiceServlet implements ExampleService{
//private Connection con=null;
private String status;
private String url="jdbc:mysql://localhost:3306/test";
private String user="test";
private String pass = "123456";
private Person people;
private ResultSet resultSet=null;
private Statement stm=null;
private Connection con=null;
private Statement stm2=null;
private Connection conn2=null;
private ResultSet resultSet2=null;
private MySqlConnection conn=new MySqlConnection();
#Override
public Person getPerson(String name,String surname,int password) {
Person personinfo=new Person();
personinfo.setName(name);
personinfo.setSurname(surname);
personinfo.setPassword(password);
ResultSet resultSet=null;
Statement stm=null;
Connection con=null;
MySqlConnection conn=new MySqlConnection();
con = conn.getConnection();
try {
stm = ((Connection) con).createStatement();
} catch (SQLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
String sorgu = "SELECT * FROM person";
try {
resultSet = stm.executeQuery(sorgu);
} catch (SQLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
while(true){
String sql = "INSERT INTO person " +
"VALUES ("+ password +", '" + name+ "','" + surname + "')";
try {
stm.executeUpdate(sql);
} catch (SQLException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
((Connection) con).setAutoCommit(false);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
((Connection) con).commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
stm.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return personinfo;
}
}
public class MySqlConnection extends RemoteServiceServlet {
private static final long serialVersionUID = 1L;
public static Connection con;
public static Connection getConnection()
{
try
{
if(con==null)
{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mysqlconn?user=root&password=123456";
con= DriverManager.getConnection(url);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return con;
}
public static void CloseConnection()
{
try
{
con.close();
con = null;
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}