Hi Mike,
thanks a lot for answering.
I don't know, if I get it completly, but am I right, if I recapitulate your answer like this: the container (JBoss 4.0.4) will check, if a pre-existed object, well, pre-existed and would inform the client about this fact?
I'm not setting version fields by myself and I don't want to persist new objects with existing version numbers.
But I can observe, that a new object will be persisted, if a merge on an unmanaged object will be executed, although the managed version of this object is not existing anymore.
What I would expect, is an exception, if a pre-existed unmanaged POJO, will be merged by the container. Is this correct? If so, how is that be implemented?
I think, this observation is the result of my absence of understanding. So please have a look at my testing code, even if this will violate the "how to ask questions the smart way" rule (if so, sorry for that).
Thanks in advance.
Rene
p.s. I surely will have a look on your book ;-)
package ejbtest;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Version;
/**
* represents an entity POJO for demonstrating EJB 3.0 persistance matters
* @author Rene
*
*/
@Entity
public class Depot implements Serializable {
private int id;
private long version;
private String name;
public Depot() {
}
public Depot(String name) {
this.name = name;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Version
protected long getVersion() {
return version;
}
protected void setVersion(long version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package ejbtest;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import ejbtest.DepotManager;
public @Stateless class DepotManagerBean implements DepotManager {
@PersistenceContext(unitName = "ejbTest")
private EntityManager manager;
public Depot addDepot(Depot depot) {
manager.persist(depot);
return depot;
}
public void removeDepot(Depot depot) {
manager.remove(depot);
}
public Depot updateDepot(Depot depot) {
return manager.merge(depot);
}
public List getAllDepots() {
Query query = manager.createQuery("from Depot");
return query.getResultList();
}
}
package ejbtest;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface DepotManager {
public Depot addDepot(Depot depot);
public void removeDepot(Depot depot);
public Depot updateDepot(Depot depot);
public List getAllDepots();
}
package ejbtest;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.List;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
/**
* is gui frame, where the user can interact with depot tree,
* to demonstrate entity bean access and currency aspects
* @author Rene
*
*/
public class Client extends JFrame implements ActionListener {
private JPanel buttonPanel;
private JTextField depotName;
private JTree tree;
private JButton addButton, removeButton, renameButton, refreshButton;
private JScrollPane scrollPane;
private Context jndiContext;
private DepotManager manager;
/**
* Client constructor
*
*/
public Client() {
try {
initManager();
initLayout();
} catch (NamingException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
}
/**
* initialyzes JNDI-Context and references DepotManager
* @throws NamingException
*/
public void initManager() throws NamingException {
jndiContext = getInitialContext();
Object managerBean = jndiContext.lookup("DepotManagerBean/remote");
manager = (DepotManager) managerBean;
}
/**
* initialyzes the GUI-component
*
*/
private void initLayout() {
buttonPanel = new JPanel();
depotName = new JTextField(10);
addButton = createButton("add");
removeButton = createButton("remove");
renameButton = createButton("rename");
refreshButton = createButton("refresh");
buttonPanel.add(depotName);
buttonPanel.add(addButton);
buttonPanel.add(removeButton);
buttonPanel.add(renameButton);
buttonPanel.add(refreshButton);
tree = createTree();
scrollPane = new JScrollPane(tree);
getContentPane().add(scrollPane, BorderLayout.CENTER);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
/**
* creates Button
* @param title sets text of button
* @return
*/
private JButton createButton(String title) {
JButton button = new JButton(title);
button.addActionListener(this);
return button;
}
/**
* creates tree of depots
* @return the tree
*/
private JTree createTree() {
List depots = manager.getAllDepots();
DefaultMutableTreeNode top = new DefaultMutableTreeNode("Depots");
Iterator it = depots.iterator();
while (it.hasNext()) {
Depot depot = (Depot) it.next();
DefaultMutableTreeNode node = new DefaultMutableTreeNode(depot);
top.add(node);
}
JTree tree = new JTree(top);
tree.setCellRenderer(new TreeCellRenderer());
tree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
return tree;
}
/**
* refreshes the tree with new data from database
*
*/
private void refreshTree() {
tree = createTree();
scrollPane.setViewportView(tree);
depotName.setText("");
}
/**
* sets the action of the buttons
*/
public void actionPerformed(ActionEvent e) {
/*
* adds new Depot with name from depotName text field,
* sends this depot to application server
* and refreshes the depot tree
*/
if (e.getSource() == addButton) {
if (!depotName.equals("")) {
Depot depot = new Depot(depotName.getText());
depot = manager.addDepot(depot);
refreshTree();
} else {
JOptionPane.showMessageDialog(this,
"Please insert depot name.", "",
JOptionPane.ERROR_MESSAGE);
}
/**
* removes the selected depot
*/
} else if (e.getSource() == removeButton) {
try {
if (tree.getLastSelectedPathComponent() != null) {
Depot depot = (Depot) ((DefaultMutableTreeNode) tree
.getLastSelectedPathComponent()).getUserObject();
manager.removeDepot(depot);
refreshTree();
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
"Depot was updated. Please refresh view.", "",
JOptionPane.ERROR_MESSAGE);
}
/**
* renames the selected depot with content of depotName text field,
* updates it on application server
*/
} else if (e.getSource() == renameButton) {
try {
if (tree.getLastSelectedPathComponent() != null) {
if (!depotName.getText().equals("")) {
Depot depot = (Depot) ((DefaultMutableTreeNode) tree
.getLastSelectedPathComponent())
.getUserObject();
depot.setName(depotName.getText());
depot = manager.updateDepot(depot);
refreshTree();
} else {
JOptionPane.showMessageDialog(null,
"Please insert depot name.", "",
JOptionPane.ERROR_MESSAGE);
}
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
"Depot was updated. Please refresh view.", "",
JOptionPane.ERROR_MESSAGE);
}
/*
* refreshes depot tree
*/
} else if (e.getSource() == refreshButton) {
refreshTree();
}
}
/**
* gets initial context
* @return context
* @throws javax.naming.NamingException
*/
public Context getInitialContext() throws javax.naming.NamingException {
return new javax.naming.InitialContext();
}
/**
* CellRenderer of depot tree
* @author Rene
*
*/
public class TreeCellRenderer extends DefaultTreeCellRenderer {
/**
* sets text of tree node to name of depot
*/
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded,
leaf, row, hasFocus);
Object o = ((DefaultMutableTreeNode) value).getUserObject();
if (o instanceof Depot) {
Depot depot = (Depot) o;
this.setText(depot.getName());
}
return this;
}
}
}