I am using Wildfly 10. I am trying to bind an entity to a jsf page and save it with jpa to my db.
I am getting a javax.servlet.ServletException: javax.ejb.EJBException: java.lang.IllegalArgumentException: Unknown entity: de.rupp.model.Contact$Proxy$_$$_WeldClientProxy javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
My persistence.xml in WEB-INF/classes/META-INF:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="contacts">
<!-- If you are running in a production environment, add a managed
data source, this example data source is just for development and testing! -->
<!-- The datasource is deployed as WEB-INF/jsftest-ds.xml, you
can find it in the source at src/main/webapp/WEB-INF/jsftest-ds.xml -->
<jta-data-source>java:/ContactsDS</jta-data-source>
<class>de.rupp.model.Contact</class>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
</properties>
</persistence-unit>
</persistence>
My Entity
@Named
@RequestScoped
@Entity
@NamedQueries({
@NamedQuery(name=Contact.FIND_ALL, query="SELECT c FROM Contact c"),
@NamedQuery(name=Contact.DELETE_ALL, query="DELETE FROM Contact")
})
public class Contact implements Serializable{
public final static String FIND_ALL = "Contacts.findAll";
public final static String DELETE_ALL = "Contacts.deleteAll";
/**
*
*/
private static final long serialVersionUID = -7050382512059267701L;
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String email;
private String phone;
private String message;
//getter and setter omitted for brevity
}
My Controller
@Named
@RequestScoped
public class EingabeController implements Serializable {
private Logger log = LoggerFactory.getLogger(EingabeController.class);
@Inject
private ContactsDAOBean contactsDAOBean;
@Inject
private Contact contact;
public void save() {
this.contactsDAOBean.save(this.contact);
log.info(this.contact + " saved");
}
}
My persistence layer works I have written an Arquillian Test for this:
@RunWith(Arquillian.class)
public class ContactsDAOTest {
@Deployment
public static Archive<?> createTestArchive() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.addClasses(Contact.class, AbstractDAO.class, AbstractDAOBean.class, ContactsDAOBean.class)
.addAsResource("META-INF/persistence.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Inject
private ContactsDAOBean contactsDAOBean;
@Before
public void init() {
contactsDAOBean.deleteAll();
}
@Test
public void save() {
Contact contact = new Contact();
contact.setEmail("h.rupp@dzbw.de");
contact.setFirstName("Hans");
contact.setLastName("Rupp");
contact.setPhone("0711 8108 276232");
contact.setMessage("Ich will hier raus");
contactsDAOBean.save(contact);
List<Contact> contacts = contactsDAOBean.findAll();
assertEquals(1, contacts.size());
}
}
Any ideas would be greatly appreciated
------------------- edit --------------------------------------
I have refactored this page: originally the Contact entity has been bound directly to the input elements like
<h:inputText value="#{contact.firstName}" styleClass="form-control"/>
I have changed the controller so that it produces the entity to be saved.
@Named
@RequestScoped
public class EingabeController implements Serializable {
@Inject
private ContactsDAOBean contactsDAOBean;
@Named
@Produces
private Contact newContact;
@PostConstruct
public void init() {
this.newContact = new Contact();
}
public String save() {
this.contactsDAOBean.save(this.newContact);
log.info(this.newContact + " saved");
this.savedContact = this.newContact;
return "data";
}
@Named
@Produces
private Contact savedContact;
}
The @Named and the @RequestScoped Annotations have been removed from the Contact eintity.
<h:inputText value="#{newContact.lastName}" styleClass="form-control" id="lastName"/>
The page works like this, the save action can be invoked without errro.
Maybe the real cause is a misunderstandig of mine how JSF and CDI are supposed to work.
I thought that in the original version - a bean which is bound to controls is instantiated when the page is rendered - the bean is filled with the values the user enters - when the save action is called the bean is injected in the controller well this might be my error in reasoning: the controller was instantiated with the page, and at that time the Contacts bean was injected, was that not the same instance like the bean bound to the controls?
I am just trying to (re-)learn JSF .... Can anybody recommend a good source which dicusses exhaustively the architecture of JSF applications? I guess I have enough books which discuss the controls etc. in isolation.