p:selectOneMenu not calling setter on form submit - jsf-2

I'm kinda new to JSF and primefaces and I'm running into a very annoying problem.
I'm making a very basic application to learn a bit more about primefaces. I have a simple form that has several textual input fields, two datepickers and one dropdown (selectOneMenu).
Everything works all values are put in the backing bean when I submit the form, except for the value from the dropdown menu. The setter for that item is never called. And the application does not call the public void saveNewActivity(ActionEvent evt) method on the controller as defined on the commandbutton. When I however remove or comment out the dropdown menu in html it does call that method (but the field for the dropdown menu is obviously null).
I've been trying things for nearly two days, and still can't get this to work properly.
I have the following code (snippets):
My html/jsf code
<div id="newActivitycontent">
<h:form id="newActivityForm">
<h:messages id="messages"/>
<table>
<tr>
<td>Gebruiker:</td>
<td><p:selectOneMenu value="#{plannedActivityController.newActivity.organiser}}"
converter="#{userConverter}">
<f:selectItem itemLabel="Kies een gebruiker" itemValue=""/>
<f:selectItems value="#{plannedActivityController.users}" var="user"
itemLabel="#{user.firstname} #{user.lastname}" itemValue="#{user}"/>
</p:selectOneMenu></td>
</tr>
<tr>
<td>Titel:</td>
<td><p:inputText value="#{plannedActivityController.newActivity.name}"/></td>
</tr>
<tr>
<td>Beschrijving:</td>
<td><p:inputText value="#{plannedActivityController.newActivity.desctription}"/></td>
</tr>
<tr>
<td>Startdatum:</td>
<td><p:calendar value="#{plannedActivityController.newActivity.startDateDate}"/></td>
</tr>
<tr>
<td>Einddatum:</td>
<td><p:calendar value="#{plannedActivityController.newActivity.endDateDate}"/></td>
</tr>
</table>
<p:commandButton id="btnSaveNewActivity" value="Opslaan"
actionListener="#{plannedActivityController.saveNewActivity}"
update=":overviewForm:activityTable messages"/>
<p:commandButton id="btnCancelNewActivity" value="Annuleren"
actionListener="#{plannedActivityController.cancelNewActivity}" onclick="hideAddNewUI()"
update=":overviewForm:activityTable" type="reset" immediate="true"/>
</h:form>
</div>
The controller that is used by that code:
#Named
#SessionScoped
public class PlannedActivityController implements Serializable {
#Inject
private ApplicationModel appModel;
#Inject
private SessionModel sessionModel;
#Inject
private ActivityMapper activityMapper;
#Inject
private UserMapper userMapper;
private ActivityBean newActivity;
private ActivityBean selectedActivity;
private List<ActivityBean> activities;
private List<UserBean> users;
public PlannedActivityController() {
}
#PostConstruct
public void onCreated() {
convertActivities();
onNewActivity();
users = userMapper.mapToValueObjects(appModel.getUsers());
}
public void convertActivities() {
List<PlannedActivity> originalActivities = appModel.getActivities();
this.activities = activityMapper.mapToValueObjects(originalActivities);
}
public void onRowEditComplete(RowEditEvent event) {
System.out.println("row edited : " + event.getObject());
//TODO: save changes back to db!
}
public void onRowSelectionMade(SelectEvent event) {
System.out.println("row selected : " + event.getObject());
selectedActivity = (ActivityBean)event.getObject();
}
//Activity crud methods
public void onNewActivity() {
newActivity = new ActivityBean();
newActivity.setId(new Date().getTime());
}
public void saveNewActivity(ActionEvent evt) {
PlannedActivity newAct = activityMapper.mapToEntity(newActivity);
if(newAct != null) {
appModel.getActivities().add(newAct);
}
convertActivities();
}
public void cancelNewActivity() {
//TODO: cleanup.
}
public void deleteSelectedActivity() {
if(selectedActivity != null) {
activities.remove(selectedActivity);
appModel.setActivities(activityMapper.mapToEntities(activities));
convertActivities();
} else {
//TODO: show error or information dialog, that delete cannot be done when nothing has been selected!
}
}
//Getters & Setters
public ApplicationModel getAppModel() {
return appModel;
}
public void setAppModel(ApplicationModel appModel) {
this.appModel = appModel;
}
public SessionModel getSessionModel() {
return sessionModel;
}
public void setSessionModel(SessionModel sessionModel) {
this.sessionModel = sessionModel;
}
public ActivityMapper getActivityMapper() {
return activityMapper;
}
public void setActivityMapper(ActivityMapper activityMapper) {
this.activityMapper = activityMapper;
}
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
public ActivityBean getNewActivity() {
return newActivity;
}
public void setNewActivity(ActivityBean newActivity) {
this.newActivity = newActivity;
}
public ActivityBean getSelectedActivity() {
return selectedActivity;
}
public void setSelectedActivity(ActivityBean selectedActivity) {
this.selectedActivity = selectedActivity;
}
public List<ActivityBean> getActivities() {
return activities;
}
public void setActivities(List<ActivityBean> activities) {
this.activities = activities;
}
public List<UserBean> getUsers() {
return users;
}
public void setUsers(List<UserBean> users) {
this.users = users;
}
}
My activitybean:
public class ActivityBean implements Serializable {
private Long id = 0L;
private String name;
private String desctription;
private UserBean organiser;
private Calendar startDate;
private Calendar endDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesctription() {
return desctription;
}
public void setDesctription(String desctription) {
this.desctription = desctription;
}
public UserBean getOrganiser() {
return organiser;
}
public void setOrganiser(UserBean organiser) {
this.organiser = organiser;
}
public Calendar getStartDate() {
return startDate;
}
public void setStartDate(Calendar startDate) {
this.startDate = startDate;
}
public Date getStartDateDate() {
if(this.startDate == null) {
return null;
}
return this.endDate.getTime();
}
public void setStartDateDate(Date startDate) {
if(this.startDate == null) {
this.startDate = new GregorianCalendar();
}
this.startDate.setTime(startDate);
}
public String getStartDateString() {
if(this.startDate == null) {
return null;
}
return startDate.get(Calendar.DAY_OF_MONTH) + "/" + startDate.get(Calendar.MONTH) + "/" + startDate.get(Calendar.YEAR) + "";
}
public Calendar getEndDate() {
return endDate;
}
public void setEndDate(Calendar endDate) {
this.endDate = endDate;
}
public Date getEndDateDate() {
if(this.endDate == null) {
return null;
}
return endDate.getTime();
}
public void setEndDateDate(Date endDate) {
if(this.endDate == null) {
this.endDate = new GregorianCalendar();
}
this.endDate.setTime(endDate);
}
public String getEndDateString() {
if(this.endDate == null) {
return null;
}
return endDate.get(Calendar.DAY_OF_MONTH) + "/" + endDate.get(Calendar.MONTH) + "/" + endDate.get(Calendar.YEAR) + "";
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActivityBean that = (ActivityBean) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
My userbean:
public class UserBean {
private Long id;
private String username;
private String firstname;
private String lastname;
private String email;
private String phone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserBean userBean = (UserBean) o;
if (id != null ? !id.equals(userBean.id) : userBean.id != null) return false;
return true;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
And the converter used by the selectOneMenu:
#Named
public class userConverter implements Converter{
#Inject
private PlannedActivityController activityController;
#Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
for (UserBean user : activityController.getUsers()) {
if(user.getId().toString().equals(s)) {
return user;
}
}
return null;
}
#Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
if(o instanceof UserBean) {
UserBean user = (UserBean)o;
return user.getId().toString();
}
return "";
}
}

The problem is here. Look closer. This is invalid EL syntax.
value="#{plannedActivityController.newActivity.organiser}}"
This should however have thrown a PropertyNotWritableException on submit something like this:
javax.el.PropertyNotWritableException: /test.xhtml #25,39 value="#{plannedActivityController.newActivity.organiser}}": Illegal Syntax for Set Operation
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
at javax.faces.component.UIInput.updateModel(UIInput.java:822)
at javax.faces.component.UIInput.processUpdates(UIInput.java:739)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1244)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1244)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1223)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
This exception should have been logged to the server log. By default this will however not end up in an error page for the enduser because JSF/PrimeFaces have by default no form of feedback to enduser in case of exceptions which are thrown during ajax requests. You should however be able to see it in actual ajax response body in webbrowser's builtin HTTP traffic monitor.
The JSF utility library OmniFaces offers a FullAjaxExceptionHandler for the very problem of total absence of feedback on exceptions during ajax requests. You may find it useful. When I tried to recreate your problem, I was been presented a clear error page so that I don't need to dig in server log or HTTP traffic monitor for clues.

Related

Thymeleaf - th:checked works, th:field fails

Thymeleaf
Im trying to bind a variable called 'permitirAcesso' to thymeleaf. When I use th:checked, it shows the value correctly. When I use th:field, it doesnt bind. What should I do?
I investigated and th:text shows the correct value. Ive also tried changing the variable name, but it still doesnt work. Ive also tried to use a common html checkbox, it still doesnt bind.
Ive simplified the page and removed everything except the form and the malfunction persists. It works with th:checked but fails to bind with th:field.
Here's my code:
<head>
<meta charset="UTF-8"/>
</head>
<body>
<form id="formulario" th:action="#{/painel-do-administrador/usuarios/salvar}" th:object="${usuario}" method="POST" class="action-buttons-fixed">
<input type="checkbox" name="permitirAcesso" id="permitirAcesso" th:field="*{permitirAcesso}" />
<input type="checkbox" name="permitirAcesso" id="permitirAcesso" th:checked="*{permitirAcesso}" />
</form>
</body>
My Java Code:
#Entity
#Table(name = "users")
public class User implements UserDetails, Comparable<User> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank(message = "O nome não pode ser nulo")
#NotNull(message = "O nome não pode ser nulo")
#Column(name = "username", nullable = false, length = 512, unique = true)
private String username;
#Column(name = "nome_completo", updatable = true, nullable = false)
private String nomeCompleto;
#Column(name = "password", updatable = true, nullable = false)
private String password;
#Column(name = "ultimo_acesso")
private ZonedDateTime ultimoAcesso;
#Email(message = "Insira uma e-mail válido")
#Column(name = "email", updatable = true, nullable = false)
private String email;
#Column(name = "permitir_acesso")
private boolean permitirAcesso;
#Lob
#Column(name = "avatar", columnDefinition = "BLOB")
private byte[] avatar;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
public User() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNomeCompleto() {
return nomeCompleto;
}
public void setNomeCompleto(String nomeCompleto) {
this.nomeCompleto = nomeCompleto;
}
#Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public ZonedDateTime getUltimoAcesso() {
return ultimoAcesso;
}
public void setUltimoAcesso(ZonedDateTime ultimoAcesso) {
this.ultimoAcesso = ultimoAcesso;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isPermitirAcesso() {
return permitirAcesso;
}
public String getPermitirAcessoString() {
if (permitirAcesso) {
return "Sim";
} else {
return "Não";
}
}
public void setPermitirAcesso(boolean permitirAcesso) {
this.permitirAcesso = permitirAcesso;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void addRole(Role role) {
this.roles.add(role);
}
public boolean hasRole(Role role) {
Iterator<Role> iterator = this.roles.iterator();
while (iterator.hasNext()) {
if (role.equals(iterator.next())) {
return true;
}
}
return false;
}
public boolean hasRole(String roleName) {
for (Role role : this.roles) {
if (role.getName().equals(roleName)) {
return true;
}
}
return false;
}
#Override
#JsonIgnore
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList();
}
#Override
public int compareTo(User o) {
return getEmail().compareToIgnoreCase(o.getEmail());
}
#Override
#JsonIgnore
public boolean isAccountNonExpired() {
return true;
}
#Override
#JsonIgnore
public boolean isAccountNonLocked() {
return true;
}
#Override
#JsonIgnore
public boolean isCredentialsNonExpired() {
return true;
}
#Override
#JsonIgnore
public boolean isEnabled() {
return isPermitirAcesso();
}
}
Ok. This was a stupid mistake of mine. So what happened is that I had a Boolean Converter that converted Boolean to String. Removing the converter, fixed the issue.

Updating adapter of AutoCompleteTextView from LiveData

I have a AutoCompleteTextView that I give it 2 different adapters depending on the amount of text that is being present at the textview - if it has 0 characters I want it to display a list of "recently searched" strings adapter, while if it has more than 1 characters I want it to display auto completion list.
My getRecentlySearchedQueries method along with the RecentSearchedViewModel-
private List<String> recentlySearchedQueries = new ArrayList<>(); // pasted from the top of the class
#Override
public void getRecentlySearchedQueries() {
recentSearchViewModel.getAllQueries().observe(getActivity(), databaseRecentlySearchList -> {
if (databaseRecentlySearchList == null) {
return;
}
for (int i = 0; i < databaseRecentlySearchList.size(); i++) {
Log.d("localDBValue", "Added value - " + databaseRecentlySearchList.get(i).toString() + "\n");
String query = databaseRecentlySearchList.get(i).getQuery();
recentlySearchedQueries.add(query);
}
//Log.d("localDBValue", "recent search list value - " + recentlySearchedQueries);
});
}
public class RecentSearchViewModel extends AndroidViewModel {
private RecentSearchRepository recentSearchRepository;
private LiveData<List<RecentSearchModel>> allRecentlySearched;
public RecentSearchViewModel(#NonNull Application application) {
super(application);
recentSearchRepository = new RecentSearchRepository(application);
allRecentlySearched = recentSearchRepository.getAllRecentSearches();
}
public void insert(RecentSearchModel model) {
recentSearchRepository.insert(model);
}
public void update(RecentSearchModel model) {
// add implementation in the future if needed
}
public void delete(RecentSearchModel model) {
// add implementation in the future if needed
}
public LiveData<List<RecentSearchModel>> getAllQueries() {
return allRecentlySearched;
}
}
public class RecentSearchRepository {
private RecentSearchDao recentSearchDao;
private LiveData<List<RecentSearchModel>> allRecentSearches;
public RecentSearchRepository(Application application) {
MarketplaceDatabase database = MarketplaceDatabase.getRecentSearchInstance(application);
recentSearchDao = database.recentSearchDao();
allRecentSearches = recentSearchDao.getRecentSearchList();
}
public void insert(RecentSearchModel model) {
new RecentSearchRepository.InsertRecentSearchAsyncTask(recentSearchDao).execute(model);
}
public void update (RecentSearchModel model) {
//TODO - implement in future if needed
}
public void delete(RecentSearchModel model) {
//TODO - implement in future if needed
}
public LiveData<List<RecentSearchModel>> getAllRecentSearches() {
return allRecentSearches;
}
private static class InsertRecentSearchAsyncTask extends AsyncTask<RecentSearchModel, Void, Void> {
private RecentSearchDao recentSearchDao;
public InsertRecentSearchAsyncTask(RecentSearchDao recentSearchDao) {
this.recentSearchDao = recentSearchDao;
}
#Override
protected Void doInBackground(RecentSearchModel... recentSearchModels) {
recentSearchDao.insert(recentSearchModels[0]);
return null;
}
}
private static class UpdateRecentSearchAsyncTask extends AsyncTask<RecentSearchModel, Void, Void> {
private RecentSearchDao recentSearchDao;
public UpdateRecentSearchAsyncTask(RecentSearchDao recentSearchDao) {
this.recentSearchDao = recentSearchDao;
}
#Override
protected Void doInBackground(RecentSearchModel... recentSearchModels) {
recentSearchDao.update(recentSearchModels[0]);
return null;
}
}
}
#Dao
public interface RecentSearchDao {
#Insert()
void insert(RecentSearchModel model);
#Update
void update(RecentSearchModel model);
#Delete
void delete(RecentSearchModel model);
#Query("select * from recent_search_table")
LiveData<List<RecentSearchModel>> getRecentSearchList();
}
#Entity(tableName = "recent_search_table")
public class RecentSearchModel {
#PrimaryKey(autoGenerate = true)
private int ID;
private String query;
public RecentSearchModel(){
}
public RecentSearchModel(String query) {
this.query = query;
}
public void setID(int ID) {
this.ID = ID;
}
public int getID() {
return ID;
}
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
#Override
public String toString() {
return "RecentSearchModel{" +
"query='" + query + '\'' +
'}';
}
#Override
public boolean equals(#Nullable Object obj) {
if (obj instanceof RecentSearchModel)
return this.query.equalsIgnoreCase(((RecentSearchModel) obj).query);
return false;
}
}
So, what I am doing here is for start getting all values inside my local DB and adding them to my String list that is part of the adapter. So far so good.
The issue I am facing is that the adapter won't show the amount of strings available in the list that populates it. In fact, it sometimes shows a view half-cut with wierd information, sometimes does not show anything and sometimes shows part of the corrent information. What am I missing?
Another thing I am facing is that the "recently searched" adapter won't work when clicking on the AutoCompleteTextView - it only works when typing and deleting values so the char length is 0. How can I make it work from start of focus?
Here is the way I am populating the information to the ViewModel -
/**
* Shows the searched products following
*/
#Override
public void getSearchedProducts(String searchedQuery) {
MarketplaceUtils.getSearchedProducts(searchedQuery, marketApiCalls, false, initialSearchTake, initialMarketplacePage, new MarketplaceUtils.OnProductsFetchCompleteListener() {
#Override
public void onSuccess(List<MiniProductModel> list) {
if (!searchedQuery.equals(currentSearchedText))
return;
if (list == null) {
//reaching here means we do not have a result to show to the UI so we empty the list.
currentProductList.clear();
productsAdapter.notifyDataSetChanged();
return;
}
if (searchedQuery.length() > 3 && searchAutoCompleteStrings.contains(searchedQuery)) {
Log.d("localDBValue", "searchedValue - " + searchedQuery);
recentSearchViewModel.insert(new RecentSearchModel(searchedQuery));
}
mPresenter.setDiscoverProductsLayoutVisibility(View.GONE);
currentProductList.clear();
currentProductList.addAll(list);
productsAdapter.notifyDataSetChanged();
}
#Override
public void onError(Throwable throwable) {
Log.d("searchedProducts", throwable.getMessage());
}
});
}
The default behaviour for #Insert method of Room is OnConflictStrategy.ABORT - so what I did is to implement equals() method to verify that the RecentSearchModels that are being compared are compared by their string value. Still does seems to effect anything.

ASP.NET MVC 5 SignalR, SqlDependency and EntityFramework 6 - the sqlparameter is already contained by another sqlparametercollection

I am beginner with SignalR and SQLDepedency. I am trying to implement SignalR using EF Code First Approach. I am getting the error The sqlparameter is already contained by another sqlparametercollection if I am using where condition in LINQ class.
public class MessageHub : Hub
{
internal NotifierEntity NotifierEntity { get; private set; }
private MyDbContext db = new MyDbContext();
public void DispatchToClient()
{
Clients.All.broadcastMessage("Refresh");
}
public void Initialize(String userName)
{
if (!string.IsNullOrEmpty(userName))
{
NotifierEntity = db.GetNotifierEntity<Messages>(db.Messages.Where(x=>x.ApplicationUser.UserName== userName && !x.Status));
if (NotifierEntity == null)
return;
Action<String> dispatcher = (t) => { DispatchToClient(); };
PushSqlDependency.Instance(NotifierEntity, dispatcher);
}
}
}
The NotifierEntity Class
public class NotifierEntity
{
ICollection<SqlParameter> sqlParameters = new List<SqlParameter>();
public String SqlQuery { get; set; }
public String SqlConnectionString { get; set; }
public ICollection<SqlParameter> SqlParameters
{
get
{
return sqlParameters;
}
set
{
sqlParameters = value;
}
}
public static NotifierEntity FromJson(String value)
{
if (String.IsNullOrEmpty(value))
throw new ArgumentNullException("NotifierEntity Value can not be null!");
return new JavaScriptSerializer().Deserialize<NotifierEntity>(value);
}
}
public static class NotifierEntityExtentions
{
public static String ToJson(this NotifierEntity entity)
{
if (entity == null)
throw new ArgumentNullException("NotifierEntity can not be null!");
return new JavaScriptSerializer().Serialize(entity);
}
}
public class PushSqlDependency
{
static PushSqlDependency instance = null;
readonly SqlDependencyRegister sqlDependencyNotifier;
readonly Action<String> dispatcher;
public static PushSqlDependency Instance(NotifierEntity notifierEntity, Action<String> dispatcher)
{
if (instance == null)
instance = new PushSqlDependency(notifierEntity, dispatcher);
return instance;
}
private PushSqlDependency(NotifierEntity notifierEntity, Action<String> dispatcher)
{
this.dispatcher = dispatcher;
sqlDependencyNotifier = new SqlDependencyRegister(notifierEntity);
sqlDependencyNotifier.SqlNotification += OnSqlNotification;
}
internal void OnSqlNotification(object sender, SqlNotificationEventArgs e)
{
dispatcher("Refresh123");
}
}
public class SqlDependencyRegister
{
public event SqlNotificationEventHandler SqlNotification;
readonly NotifierEntity notificationEntity;
internal SqlDependencyRegister(NotifierEntity notificationEntity)
{
this.notificationEntity = notificationEntity;
RegisterForNotifications();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security",
"CA2100:Review SQL queries for security vulnerabilities")]
void RegisterForNotifications()
{
using (var sqlConnection = new SqlConnection(notificationEntity.SqlConnectionString))
using (var sqlCommand = new SqlCommand(notificationEntity.SqlQuery, sqlConnection))
{
foreach (var sqlParameter in notificationEntity.SqlParameters)
{
sqlCommand.Parameters.Add(sqlParameter);
}
sqlCommand.Notification = null;
var sqlDependency = new SqlDependency(sqlCommand);
sqlDependency.OnChange += OnSqlDependencyChange;
if (sqlConnection.State == ConnectionState.Closed)
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
}
}
void OnSqlDependencyChange(object sender, SqlNotificationEventArgs e)
{
if (SqlNotification != null)
SqlNotification(sender, e);
RegisterForNotifications();
}
}
public delegate void SqlNotificationEventHandler(object sender, SqlNotificationEventArgs e);
If I am using the same query without any parameters, the code is working perfectly. I can see the database changes instantly in frontend. The issue is coming after added a parameter in Where clause.
I got this idea from below link
https://www.codeproject.com/Tips/1075852/ASP-NET-MVC-SignalR-SqlDependency-and-EntityFramew
Sourcecode link
we.tl/njwwLl8g36

Flash Scope does not delete variables

I'm having a problem with Flash Scope when I try to set a flash scope variable and then do a redirect. In the console, I get the following trace...
com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing
cookie for the flash. Any values stored to the flash will not be available on the next request.
The idea is pass an id from the first page (search page) to the second page, but if I cancel using immediate, I get the mentioned log, and the flash counter is not incremented anymore.
The code:
(Search bean)
#ManagedBean
#ViewScoped
public class ConsultarPaisBean implements Serializable {
private static final long serialVersionUID = 7947494818704255376L;
#ManagedProperty("#{flash}")
private Flash flash;
#ManagedProperty("#{paisService}")
private PaisService paisService;
private List<Pais> paises;
private PaisFilter paisFilter;
private Pais paisSelected;
#PostConstruct
public void init() {
this.paisFilter = new PaisFilter();
this.paisSelected = null;
this.paises = null;
}
public String irRegistrarPais() {
return MappingUrlConstants.PAIS;
}
public String irModificarPais() {
String respuesta = null;
if (this.paisSelected != null && this.paisSelected.getId() != null) {
flash.put("paisId", this.paisSelected.getId());
respuesta = MappingUrlConstants.PAIS;
}
return respuesta;
}
public String buscarPaises() {
this.paisSelected = null;
this.paises = this.paisService.getPaisByParams(this.paisFilter);
return null;
}
public String limpiarFiltros() {
this.paisFilter = new PaisFilter();
return null;
}
public List<Pais> getPaises() {
return paises;
}
public void setPaises(List<Pais> paises) {
this.paises = paises;
}
public PaisFilter getPaisFilter() {
return paisFilter;
}
public void setPaisFilter(PaisFilter paisFilter) {
this.paisFilter = paisFilter;
}
public Pais getPaisSelected() {
return paisSelected;
}
public void setPaisSelected(Pais paisSelected) {
this.paisSelected = paisSelected;
}
public void setPaisService(PaisService paisService) {
this.paisService = paisService;
}
public void setFlash(Flash flash) {
this.flash = flash;
}
}
(Add/Update bean)
#ManagedBean
#ViewScoped
public class PaisBean implements Serializable {
private static final long serialVersionUID = 3604521826400240955L;
#ManagedProperty("#{paisService}")
private PaisService paisService;
#ManagedProperty("#{flash}")
private Flash flash;
private Pais pais;
#PostConstruct
public void init() {
if (this.flash.get("paisId") != null) {
Long id = (Long) this.flash.get("paisId");
this.pais = this.paisService.getPaisById(id);
} else {
this.pais = new Pais();
}
}
public String registrarPais() {
String mensajeExito = null;
if (this.pais.getId() == null) {
this.paisService.save(this.pais);
mensajeExito = MessageUtils.getMessage("org.siae.commons.messages.general", "pais.registrar.exito",
new Object[] { this.pais.getNombre() });
} else {
this.paisService.update(this.pais);
mensajeExito = MessageUtils.getMessage("org.siae.commons.messages.general", "pais.modificar.exito",
new Object[] { this.pais.getNombre() });
}
FacesUtils.addInfoMessage(mensajeExito);
return MappingUrlConstants.CONSULTAR_PAIS;
}
public String irConsultarPais() {
return MappingUrlConstants.CONSULTAR_PAIS;
}
public void setPaisService(PaisService paisService) {
this.paisService = paisService;
}
public void setFlash(Flash flash) {
this.flash = flash;
}
public Pais getPais() {
return pais;
}
public void setPais(Pais pais) {
this.pais = pais;
}
}
I appreciate your help.

Struts 2 jquery grid component with jquery grid column type list which takes list of objects

The problem I have is that I am trying to have a multi select data grid column which will have a List objects (productsEntitled).
I've got the products to display properly by providing a buildSelect custom function to populate my Edit Dialog Box when a user click edit on a record.
When I have the column with the multi select <sjg:gridColumn name="productsEntitledListModel on my grid, the save functionality does not work and does not save. I don't see any errors on the browser console nor on the java console.
Any help will be appreciated as I am unable to find out what the problem is, I de-compiled the entire show case jar and nothing that helps with this issue.
My model look like this:
#Entity
#Table ( name = "USERS")
public class User {
private Long id;
private String name;
private String username;
private String password;
private String sourceIp;
private Device device;
private List<Product> productsEntitled;
This is my grid on a jsp page:
<s:url id="remoteurl" action="loadUsersJson"/>
<s:url id="editurl" action="editGridUserEntry"/>
<s:url id="selectproductsurl" action="loadProductsJson"/>
<sjg:grid gridModel="users"
id="gridUsers"
dataType="json"
width="1150"
href="%{remoteurl}"
draggable="true"
pager="true"
resizable="true"
navigatorAddOptions="{height:525, width:425, readAfterSubmit:true, draggable:true, resizable:true}"
navigatorEditOptions="{height:525, width:425, reloadAfterSubmit:true, draggable:true, resizable:true}"
navigatorDeleteOptions="{height:200, width:200, reloadAfterSubmit:true, draggable:true, resizable:true}"
editurl="%{editurl}"
navigator="true"
navigatorEdit="true"
navigatorAdd="true"
navigatorView="true"
navigatorDelete="true"
rowList="10,15,20"
rowNum="15"
multiselect="false"
onSelectRowTopics="rowselect">
<sjg:gridColumn name="id" editable="true" index="id" hidden="true" key="true" title="ID"/>
<sjg:gridColumn name="name" index="name" editable="true" edittype="text" title="NAME"/>
<sjg:gridColumn name="sourceIp" index="sourceIp" editable="true" edittype="text" title="SOURCE IP"/>
<sjg:gridColumn name="username" index="username" editable="true" edittype="text" title="USERNAME"/>
<sjg:gridColumn name="password" index="password" editable="true" edittype="password" title="PASSWORD"/>
<sjg:gridColumn name="role" index="role" editable="true" edittype="select" editoptions="{value:'Admin:Admin;User:User;'}" title="ROLE"/>
<sjg:gridColumn name="deviceId" jsonmap="device.id" key="true" hidden="true" editable="text" title="DEVICE ID"/>
<sjg:gridColumn name="deviceIp" jsonmap="device.ip" editable="true" edittype="text" title="DEVICE IP"/>
<sjg:gridColumn name="productsEntitledListModel"
width="300"
editable="true"
edittype="select"
editoptions="{dataUrl: '%{selectproductsurl}', multiple:true, buildSelect:customBuildSelect}"
title="PRODUCTS"/>
</sjg:grid>
These are my action classes:
Show the grid:
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
public class AdminAction extends ActionSupport implements ServletRequestAware {
private static final long serialVersionUID = -1090720652366248768L;
private static final Log logger = LogFactory.getLog(AdminAction.class);
private HttpServletRequest request;
private AuthenticationTicket ticket;
private AdminService adminService;
private List<User> users;
private List<Product> products;
//private List<String>productsAllList;
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public AuthenticationTicket getTicket() {
return ticket;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public void setTicket(AuthenticationTicket ticket) {
this.ticket = ticket;
}
#Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String redirectUsersTab() {
return "users";
}
public String redirectProductsTab() {
return "products";
}
private void initAdminService () {
logger.debug("initAdminService()...");
if (adminService == null) {
adminService = (AdminService)ServiceFinder.getContext(request).getBean("adminService");
}
}
public String loadUsersJson() {
initAdminService();
this.users = adminService.getUsersAll();
return "success";
}
public String loadProductsJson() {
initAdminService();
this.products = adminService.getProductsAll();
return "success";
}
//TODO: clean up
public String getAllProductsList() {
logger.debug("testParam, userId: " + this.userId);
initAdminService();
List<Product> temp = adminService.getProductsAll();
if (userId != null) {
User userTemp = new User();
userTemp.setId(new Long(userId));
List<Product> prodEntitled = adminService.getProductsByUser(userTemp);
logger.debug("Products entitled: " + prodEntitled);
}
//TODO: merge prod and prod entitled to Model to populate the grid
products = temp;
/*
if (temp != null && temp.size() > 0) {
this.productsAllList = new ArrayList<String>();
for (Product p : temp) {
this.productsAllList.add(p.getName());
}
}
*/
//logger.debug("this.productsAllList: " + this.productsAllList);
return "success";
}
}
Class to edit the grid:
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
public class EditUsersGridAction extends ActionSupport implements ServletRequestAware {
private static final Log logger = LogFactory.getLog(EditUsersGridAction.class);
private static final long serialVersionUID = -5485382508029951644L;
private HttpServletRequest request;
private AdminService adminService;
private String oper = "";
private Long id;
private String name;
private String sourceIp;
private String password;
private String username;
private Long deviceId;
private String deviceIp;
private String devicePortDescription;
private String devicePortLayer;
private String deviceType;
private List<Product>productsEntitled;
private List<GridColumnListModel> productsEntitledListModel;
private List<Product>productsAvailable;
public List<GridColumnListModel> getProductsEntitledListModel() {
try {
if (productsEntitled != null && productsEntitled.size() > 0) {
productsEntitledListModel = new ArrayList<EditUsersGridAction.GridColumnListModel>();
for (Product p : productsEntitled) {
GridColumnListModel tmp = new GridColumnListModel();
tmp.setName(p.getName());
tmp.setValue(p);
productsEntitledListModel.add(tmp);
}
return this.productsEntitledListModel;
}else {
return null;
}
} catch (Exception ex) {
logger.error("Exception in getProductsEntitledString", ex);
return null;
}
}
public void setProductsEntitledListModel(List<GridColumnListModel> productsEntitledListModel) {
this.productsEntitledListModel = productsEntitledListModel;
}
public Long getDeviceId() {
return deviceId;
}
public void setDeviceId(Long deviceId) {
this.deviceId = deviceId;
}
public String getDeviceIp() {
return deviceIp;
}
public void setDeviceIp(String deviceIp) {
this.deviceIp = deviceIp;
}
public String getDevicePortDescription() {
return devicePortDescription;
}
public void setDevicePortDescription(String devicePortDescription) {
this.devicePortDescription = devicePortDescription;
}
public String getDevicePortLayer() {
return devicePortLayer;
}
public void setDevicePortLayer(String devicePortLayer) {
this.devicePortLayer = devicePortLayer;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public String getOper() {
return oper;
}
public void setOper(String oper) {
this.oper = oper;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSourceIp() {
return sourceIp;
}
public void setSourceIp(String sourceIp) {
this.sourceIp = sourceIp;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<Product> getProductsEntitled() {
return productsEntitled;
}
public void setProductsEntitled(List<Product> productsEntitled) {
this.productsEntitled = productsEntitled;
}
public List<Product> getProductsAvailable() {
return productsAvailable;
}
public void setProductsAvailable(List<Product> productsAvailable) {
this.productsAvailable = productsAvailable;
}
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
#Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
private void initAdminService () {
logger.debug("initAdminService()...");
if (adminService == null) {
adminService = (AdminService)ServiceFinder.getContext(request).getBean("adminService");
}
}
public String execute() throws Exception {
logger.debug("#### IN EditGridUsersAction ###");
initAdminService();
productsAvailable = adminService.getProductsAll();
User user = new User();
user.setName(name);
user.setPassword(password);
user.setUsername(username);
user.setSourceIp(sourceIp);
Device device = new Device();
device.setId(deviceId);
device.setIp(deviceIp);
device.setPortDescription(devicePortDescription);
device.setType(deviceType);
user.setDevice(device);
if (id != null) {
user.setId(id);
}
if (oper.equalsIgnoreCase("add")) {
logger.debug("products selected");
//user.setProductsEntitled(adminService.getProductsAll());
adminService.addUser(user);
} else if ( oper.equalsIgnoreCase("edit")) {
//TODO: convert model to products and add to user
logger.debug("now in edit");
List<Product> tempProd = new ArrayList<Product>();
for (GridColumnListModel gridColModel : productsEntitledListModel) {
tempProd.add(gridColModel.getValue());
}
user.setProductsEntitled(tempProd);
adminService.updateUser(user);
//return "input";
}else if (oper.equalsIgnoreCase("del")) {
logger.debug("in delete");
adminService.deleteUser(user);
}
return "success";
}
public class GridColumnListModel {
private String name;
private Product value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Product getValue() {
return value;
}
public void setValue(Product value) {
this.value = value;
}
}
}

Resources