sorry if this is a poor question but this one feature have been driving me mad for days so i thought id post it here to see if you guys can help me
basically all i want to do from a jsf page have the user search a user and for me to return all the details
<h:form id="searchForm">
<h:outputLabel value="Search: " style="font-weight:bold" />
<h:inputText id="search" value="#{userdetailsController.search}" />
<h:commandButton value="Search" action="index"/>
</h:form>
that is the jsf page, working fine
it calls my userdetailsController class
#Named("userdetailsController")
#SessionScoped
public class UserdetailsController implements Serializable {
private Userdetails current;
private DataModel items = null;
#EJB
private Richard.beans.UserdetailsFacade ejbFacade;
private PaginationHelper pagination;
private int selectedItemIndex;
private String search;
public String getSearch() {
System.out.println("inGetSearch");
return search;
}
public void setSearch(String search) {
this.search = search;
}
......
a contactsService class
#Stateless
public class ContactsService {
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
#EJB
private UserdetailsFacade cf;
public List<Userdetails> searchByString(String string) {
return cf.searchByString(string);
}
public List<Userdetails> getAllPersons() {
return cf.findAll();
}
}
an AbstractFacade class
/* trying out a search function */
public List<T> searchByString(String string) {
System.out.println("in SearchByString");
return getEntityManager().createNamedQuery("Userdetails.findByUsername").setParameter("string", "%" + string + "%").getResultList();
}
and the Userdetails class with the query i am trying to search
#NamedQuery(name = "Userdetails.findByUsername", query = "SELECT u FROM Userdetails u WHERE u.username = :username")})
currently only the getters and settings are working in Getsearch
how can i make this work as i have spent days on this feature and are still no closer, sorry this is my first time at this
thanks guys
EDIT
would adding
public List<Userdetails> getAllPersons() {
if (search == null) {
return cs.getAllPersons();
}
return cs.searchByString(search);
}
in the UserdetailsController be enough ?
You're not invoking any action here:
<h:commandButton value="Search" action="index"/>
So it's indeed logical that it isn't "doing anything".
You need to invoke a managed bean action which in turn executes the desired code to obtain the desired data from the DB and assign to a property:
<h:commandButton value="Search" action="#{userdetailsController.submit}" />
with inside UserdetailsController:
private String search;
private List<UserDetail> items; // No need for DataModel here.
#EJB
private UserdetailsFacade ejbFacade;
public String submit() {
items = ejbFacade.searchByString(search);
return "index";
}
Your whole ContactsService seems useless by the way.
As per your attempt in the getter method in the update of your question, please don't do that. You should never call the DB in a getter method for the reasons mentioned in Why JSF calls getters multiple times
Related
I have a simple form :
<h:form>
<h:inputText value="#{storyController.story.author}"/>
<h:commandButton action="#{storyController.save}" value="save"/>
</h:form>
and a bean like this :
#Model
public class Story {
private String author;
//getter and setter...
}
and a controller :
#Model
public class StoryController {
private StoryService storyService;
private Story story;
#Inject
public StoryController(StoryService storyService, Story story) {
this.storyService = storyService;
this.story = story;
}
public String save() {
System.out.println(story.getAuthor());
return "index.xhtml";
}
public Story getStory() {
return story;
}
public void setStory(Story story) {
this.story = story;
}
}
Now when I fill the author field and click on save button, the bean is not populated (the bean is injected correctly, it's not null).
If instead I do story = new Story() in constructor, then the bean is correctly populated. I want to avoid doing, this, I think that injecte bean is a better practice right?
I tried to set input value like : #{story.author} but still not populated.
What am I doing wrong?
i trie to run this code
#ManagedBean
#ApplicationScoped
public class Controller implements Serializable {
private static final long serialVersionUID = 1L;
private Benutzer benutzer;
private List<Erfasst> bisherErfasst = new ArrayList<Erfasst>();
private EntityManagerFactory emf = Persistence
.createEntityManagerFactory("CP Kontrolle");
private static Controller instance = new Controller();
public Benutzer getBenutzer() {
return benutzer;
}
public boolean anmelden(String email, int kdnr) {
EntityManager em = emf.createEntityManager();
Query query = em
.createQuery("SELECT b FROM Benutzer b WHERE b.email = :email AND b.kdnr = :kdnr");
query.setParameter("email", email);
query.setParameter("kdnr", kdnr);
List<Benutzer> liste = query.getResultList();
em.close();
if (liste.size() == 1) {
benutzer = liste.get(0);
AngemeldeteBenutzer.getAb().hinzufuegen(benutzer);
return true;
} else {
return false;
}
}
public static Controller getInstance() {
return instance;
}
[....]
}
}
The above code is my ControllerBean. From the Login-Form, user data will be checked in the "anmelden" Class and return true or false if it was successfully.If successfully, the user will be store into a list, as you can see.
#ManagedBean
#ApplicationScoped
public class AngemeldeteBenutzer implements Serializable {
private static final long serialVersionUID = 1L;
private List<Benutzer> online = new LinkedList<Benutzer>();
private static AngemeldeteBenutzer ab = new AngemeldeteBenutzer();
public static AngemeldeteBenutzer getAb() {
return ab;
}
public List<Benutzer> getOnline() {
return online;
}
public void hinzufuegen(Benutzer benutzer) {
online.add(benutzer);
}
}
This is my other Bean, which store the successfully logged user into a list.
Now i want to list all user into my table, but my table is still empty. No errors!
<h:panelGrid columns="2" id="onlinePanel" >
<h:dataTable value="#{angemeldeteBenutzer.online}" var="on">
<h:column>
<f:facet name="header">Email</f:facet>
<h:outputText value="#{on.email}"></h:outputText>
</h:column>
</h:dataTable>
</h:panelGrid>
The mistake is here:
private static Controller instance = new Controller();
public static Controller getInstance() {
return instance;
}
private static AngemeldeteBenutzer ab = new AngemeldeteBenutzer();
public static AngemeldeteBenutzer getAb() {
return ab;
}
You seem to have missed the point of a bean management framework with dependency injection support. You seem to be expecting that #{angemeldeteBenutzer} in the JSF page is referring exactly the same instance as you manually created there with new operator and are filling with users.
This is Wrong! You have there two instances of the class, one automatically created by JSF and available via #{angemeldeteBenutzer} and another one manually created by yourself and available via that getAb() method only.
Get rid of all those static fields and methods. They don't belong there. Instead, use #ManagedProperty to let JSF inject managed beans in each other. Add this code to the Controller class.
#ManagedProperty("#{angemeldeteBenutzer}")
private AngemeldeteBenutzer ab;
public AngemeldeteBenutzer getAb() {
return ab;
}
public void setAb(AngemeldeteBenutzer ab) {
this.ab = ab;
}
And replace in the same Controller class this line
AngemeldeteBenutzer.getAb().hinzufuegen(benutzer);
by
ab.hinzufuegen(benutzer);
Note: if you're already on Java EE 7, consider using CDI #Named instead of JSF #ManagedBean. When injecting via #Inject instead of #ManagedProperty, you don't need those ugly getter/setter anymore.
#Named
#ApplicationScoped
public class AngemeldeteBenutzer {
}
#Named
#ApplicationScoped
public class Controller {
#Inject
private AngemeldeteBenutzer ab;
}
Unrelated to the concrete problem, the Controller doesn't seem to be a legit application scoped bean. It looks too much like a view scoped bean due that view-specific variables and business logic. Make sure you understand the scopes: How to choose the right bean scope?
I'm currently trying to learn JSF and JPA. I know that the patterns I use are not recommended at all, but I want to understand what's going on because I think it'll help me in the future. I've just thrown together a prototype from various sources.
The problem that I encounter with the setup described below is that apparently the JPA entities are getting detached all the time, which in turn happens because the backing bean gets serialized over and over. In fact, if I remove the Serializable interface from the entity class, I get Exiting serializeView - Could not serialize state: com.sk.Message
Since the entities are detached, nothing gets committed to the database when I call EntityManager.commit(). If I manually merge all the entities (the commented out line in onCellEdit() below) with EntityManager.merge(), the modified entities are committed to the database.
I've already found from other SO posts that I could deal with this problem by adding
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
to my persistence.xml. But it was also pointed out somewhere that this would only be a workaround and not a solution.
So my questions are:
Is it intended/expected that a #ViewScoped JSF backing bean gets serialized over and over again (while staying on the same view all the time), which makes it difficult to use JPA entities in it?
Is it safe/reasonable to use the SERIALIZE_STATE_IN_SESSION parameter?
As I found recommended many times, should I just forget about JSF managed beans altogether and go with CDI directly (e.g. #ConversationScope to achieve something similar)?
I'm using TomEE (MyFaces, OpenJPA) with PrimeFaces. The backing bean contains the following code:
#ViewScoped
#ManagedBean
public class MessageBean implements Serializable
{
private List<Message> messages;
public List<Message> getMessages()
{
return messages;
}
public void setMessages( List<Message> messages )
{
this.messages = messages;
}
#PostConstruct
public void init()
{
messages = PersistenceManager.getInstance().queryMessages();
}
public void onCellEdit( CellEditEvent event )
{
// PersistenceManager.getInstance().mergeMessages( messages );
PersistenceManager.getInstance().commitTransaction();
}
[...]
A Message is a JPA Entity, like this:
#Entity
#Table( name = "message" )
#NamedQuery( name = "Message.findAll", query = "SELECT a FROM Message a" )
public class Message implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#Column( unique = true, nullable = false )
private Integer dbid;
#Column( nullable = false, length = 14 )
private String no;
[...]
}
The backing bean is referenced from a JSF page using a PrimeFaces DataTable:
<h:form id="navForm">
<p:dataTable
id="messages"
value="#{messageBean.messages}"
var="message"
editable="true"
editMode="cell">
<f:facet name="header">MESSAGE</f:facet>
<p:ajax
event="cellEdit"
listener="#{messageBean.onCellEdit}"
update=":navForm:messages" />
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{message.no}" />
</f:facet>
<f:facet name="input">
<p:inputText
id="modelInput"
value="#{message.no}" />
</f:facet>
</p:cellEditor>
<f:facet name="header">Message number</f:facet>
</p:column>
[...]
I know I'm probably violating dozens of best practices here, but for prototyping I've created a singleton POJO, PersistenceManager, which deals with the JPA interface (and potentially other data sources). I use an application-managed, resource-local EntityManager. An excerpt looks like this:
public class PersistenceManager
{
private static PersistenceManager INSTANCE;
private EntityManagerFactory emf;
private EntityManager em;
private EntityTransaction entr;
private PersistenceManager( PersistenceType persistenceType )
{
emf = Persistence.createEntityManagerFactory( "MessagePU" );
em = emf.createEntityManager();
}
public List<Message> queryMessages()
{
TypedQuery<Message> query = em.createNamedQuery( "Message.findAll", Message.class );
return query.getResultList();
}
public void commitTransaction()
{
if ( entr != null && entr.isActive() )
{
entr.commit();
}
}
[...]
Before committing a transaction you have to start it (then close it at the end of the transaction). Where is the else statement in your commitTransaction method, in case the EntityTransaction object is not active and/or null ?
Plus, I don't see any EJB in your code. The POJO approach is not the best option in an application managed, served, and hosted by a container.
For me, the best approach to implement the persistence layer in JSF and JavaEE applications in general, is the Session Façade Pattern, you can search the web about it, there are plenty of references.
In your case, something like this would do.
A Message Facade, that manages transactions related to the Message entity.
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless
public class MessageFacade extends AbstractFacade<Message> {
#PersistenceContext(unitName = "MessagePU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public MessageFacade() {
super(Message.class);
}
public List<Message> queryMessages()
{
TypedQuery<Message> query = em.createNamedQuery( "Message.findAll", Message.class );
return query.getResultList();
}
}
An abstract facade class implementing generic persistence functions on generic entities.
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public T edit(T entity) {
return getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
Your managed bean would then be something like :
#ViewScoped
#ManagedBean
public class MessageBean implements Serializable
{
#EJB
private MessageFacade messageFacade;
private List<Message> messages;
public List<Message> getMessages()
{
return messages;
}
public void setMessages( List<Message> messages )
{
this.messages = messages;
}
#PostConstruct
public void init()
{
messages = messageFacade.findAll();
}
public void onCellEdit( CellEditEvent event )
{
messageFacade.edit(messages);
}
}
I do know that similar problem was announced here few times but I spent a lot of time and still have no idea why that code doesn't work :/
This is my JSF page:
<h:form>
<h:selectOneMenu value="#{productBean.productName}">
<f:selectItems value="#{productBean.products}" var="c" itemValue="#{c.name}"/>
</h:selectOneMenu>
</h:form>
This is my productBean:
public class ProductBean extends Connector
{
private List<Product> products;
private Product product;
private String productName;
//setters and getters
public List<Product> getProducts() throws SQLException
{
resultSet = statement.executeQuery("SELECT * FROM dbo.products");
products = new ArrayList<Product>();
while(resultSet.next())
{
product = new Product();
product.setId_product(resultSet.getInt("id_product"));
product.setName(resultSet.getString("name"));
product.setCategory(resultSet.getInt("category_id"));
product.setIs_available(resultSet.getInt("is_available"));
products.add(product);
}
return products;
}
}
And finally product class:
public class Product
{
private int id_product;
private String name;
private int price;
private int category;
private int is_available;
/setters and getters
}
My goal is to have a menu list with products names. All i got in the expanded list are references.
I also tried to declare everything in the bean class and make ArrayList instead of ArrayList but i think it's not nice. It did't work anyway.
Tell me if I understand it corectly. productBean.productName is some kind of holder. productBean.products is a whole Products list and the c.name means that I want only name from the actual product.
You must also include the itemLabel :
<f:selectItems value="#{productBean.products}" var="c" itemValue="#{c.name}" itemLabel="#{c.name}" />
I am using the following piece of code in my JSF 2.0 with RichFaces 4.0. I have a managed bean that has an enum. Now i want to assign the value of the enum via an ActionParam. How can I do this? Here is the code:
<a4j:commandLink id="pendingTransactions"
action="#{tellerBean.getPendingTransactions}" value="Show Pending"
styleClass="button category-btn">
<a4j:actionparam name="first" value=""
assignTo="" />
</a4j:commandLink>
and my managed bean:
#ManagedBean
#SessionScoped
public class TellerBean implements Serializable{
public enum TransactionType {
PENDING,PROCESSED,ALL
}
private static final long serialVersionUID = -321111;
private String recipientID;
private String recipientName;
private String transactionAmount;
private TransactionType transactionType;
public String getRecipientID() {
return recipientID;
}
public void setRecipientID(String recipientID) {
this.recipientID = recipientID;
}
public String getRecipientName() {
return recipientName;
}
public void setRecipientName(String recipientName) {
this.recipientName = recipientName;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public void searchTransactions() {}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
public void getTransactions() {}
}
Now I want to assign the value of the transactionType variable to an Enum value. How can I do this?
I don't know what you want to do with the variable or how you want to display it, so here's a generic example.
First of all, the JSF page must be able to 'iterate' over the enum to discover the possible values. I'm using h:selectOneMenu as an example which is filled using f:selectItems. f:selectItems expects a List<> as input so we need to create a method in the TellerBean:
public List<TransactionType> getTransactionTypes()
{
List<TransactionTypes> tt = new ArrayList<TransactionType>();
for (TransactionType t : TransactionType.values())
{
tt.add(new TransactionType(t, t.toString()))
}
return tt;
}
Then for an example JSF page:
<h:form>
<h:selectOneMenu value="#{tellerBean.transactionType}">
<f:selectItems value="#{tellerBean.transactionTypes}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" action="#{tellerBean.someMethod}"/>
</h:form>
The JSF page should display a drop-down list with the values of the enum. When clicking the button labeled "Submit" it executes someMethod() in TellerBean. Of course this doesn't work because the method doesn't exist, but it's just an example. ;-)