I have the following form in a Struts2 JSP that contains some radio buttons. There are 2 other forms on the page that work correctly, but this one doesn't. I have determined that the value selected is somehow not being passed, and that that is the reason I'm getting a NullPointerException, but I can't figure out why it's happening. Can anyone help me? Here is my JSP form.
<s:form action="ProcessPoll3">
<table>
<tr>
<td><b><i>Poll #3</i></b></td>
<td>How many kids do you have?</td>
<td><s:radio name="poll3"
list="#{'1':'0.', '2':'1.', '3':'2.',
'4':'3.', '5':'More than 3.'}" />
<s:submit value="Vote Poll #3" align="left" /></td>
</tr>
</table>
</s:form>
My DAO class gets called with this line (and it is being called, for sure):
String poll3;
private HttpServletResponse response;
public String getPoll3() {
return poll3;
}
public void setPoll2(String poll3) {
this.poll3 = poll3;
}
public String execute() {
Poll3DAO poll3DAO = new Poll3DAO();
if (poll3DAO.tallyVote(poll3).equals("success")) {
// Processing goes on here, not relevant to this problem
}
Here is the method in the DAO class, with the breakdown point marked because the parameter that was supposed to be passed was null.
public String tallyVote(String vote) {
String successfulWrite;
request = ServletActionContext.getRequest();
SessionFactory sessionFactory = (SessionFactory) request.getSession()
.getServletContext().getAttribute("sessionFactory");
Session session = sessionFactory.openSession();
try {
// Get previous results
Transaction tx1 = session.beginTransaction();
Query myQuery = session.createQuery("from Poll3");
tx1.commit();
// Update results
Iterator<Poll3> iterate = myQuery.iterate();
Poll3 poll3 = iterate.next();
// NullPointerException occurs on next line
if (vote.equals("1")) {
poll3.setZero(poll3.getZero() + 1);
} else if (vote.equals("2")) {
poll3.setOne(poll3.getOne() + 1);
} else if (vote.equals("3")) {
poll3.setTwo(poll3.getTwo() + 1);
} else if (vote.equals("4")) {
poll3.setThree(poll3.getThree() + 1);
} else if (vote.equals("5")) {
poll3.setMoreThanThree(poll3.getMoreThanThree() + 1);
}
// Write new results back to database;
Transaction tx2 = session.beginTransaction();
session.update(poll3);
tx2.commit();
successfulWrite = "success";
} catch (Exception e) {
System.out.println(e.toString());
successfulWrite = "failure";
}
return successfulWrite;
}
I'm betting it's this:
public void setPoll2(String poll3) { ... }
This is why we have map/collection support to avoid writing cut-and-paste blobs like this.
Any time you find yourself cutting and pasting code like in your snippets it's generally because an abstraction has been ignored/overlooked.
Related
I have trouble getting data here from database there isn't data,
Data is not displayed outside of the method.
Could you please help me?
List<Person> Refresh() {
Person p = new Person();
ParseQuery <ParseObject> query = ParseQuery.getQuery(NAME_DATABASE);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scoreList , ParseException e) {
if (e == null) {
for (int i = 0; i < scoreList.size(); i++){
p.setId(scoreList.get(i).getInt(Key.ID));
p.setName(scoreList.get(i).getString(Key.NAME));
p.setAge(scoreList.get(i).getString(Key.AGE)); p.setDate_start(scoreList.get(i).getString(Key.DATE_START));
p.setMonth_number(scoreList.get(i).getString(Key.MONTH_NUMBER));
p.setPropriety(scoreList.get(i).getString(Key.PROPRIETY));
p.setPrice(scoreList.get(i).getString(Key.PRICE));
p.setGender(scoreList.get(i).getString(Key.GENDER));
persons.add(p); //there is find data
}
}
else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
return persons; //here there isn't data (size=0)
}
The answer is simple really. You are returning persons outside the findInBackground() method.
else{
Log.d("score", "Error: " + e.getMessage());
}
//Return here after the else statement
return persons;
}
Note : you might want to make persons a global variable or else android studio will tell you to declare it as a final variable.
I am using a dbContextwhich is described as the following
public class DbContext: System.Data.Entity.DbContext
{
public DbSet<UserAccount> UserAccounts { get; set; }
public DbSet<Sesison> Sessions { get; set; }
}
And in my login action for some reason after checking with the database that the user is correct i am not able to use another entity of the context to save into the database, whats happens is that i won't get the data saved into the database and it will actually stop executing code after the dc.SaveChanges() but i dont get an exeption on my catch, so what my browser is expiriencing is a 500 internal server error.
public ActionResult Login(LoginViewModel model)
{
using (DbContext dc = new DbContext())
{
var v = dc.UserAccounts.SingleOrDefault(a => a.UserName == model.UserName);
if (v != null)
{
if (GetSHA1(model.Password) == v.Password)
{
Guid sessionGuid =Guid.NewGuid();
var session = dc.Sessions.Add(new Sesison() { SessionID = sessionGuid,StartDateTime=DateTime.UtcNow,UserID = v.UserID,ExpireDateTime=DateTime.UtcNow.AddHours(4)});
System.Web.HttpContext.Current.Session["IsLogin"] = true;
System.Web.HttpContext.Current.Session["Session"] = sessionGuid;
try
{
dc.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
Exception raise = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
string message = string.Format("{0}:{1}",
validationErrors.Entry.Entity.ToString(),
validationError.ErrorMessage);
// raise a new exception nesting
// the current instance as InnerException
raise = new InvalidOperationException(message, raise);
}
}
throw raise;
}
return Json(new
{
Item1 = "true"
});
}
else
{
return Json(new
{
Item1 = "false",
Item2 = "The username or password you entered is incorrect. Please try again."
});
}
}
else
{
return Json(new
{
Item1 ="false",
Item2 = "The username or password you entered is incorrect. Please try again."
});
}
}
return null;
}
The call to SaveChanges is throwing an exception of a type other than DbEntityValidationException
A quick look at the DbContext SaveChanges call shows that it might throw the following types of exceptions. If you don't want to handle each then you probably want to add a generic Exception handling to find the problem.
// Exceptions:
// T:System.Data.Entity.Infrastructure.DbUpdateException:
// An error occurred sending updates to the database.
//
// T:System.Data.Entity.Infrastructure.DbUpdateConcurrencyException:
// A database command did not affect the expected number of rows. This usually indicates
// an optimistic concurrency violation; that is, a row has been changed in the database
// since it was queried.
//
// T:System.Data.Entity.Validation.DbEntityValidationException:
// The save was aborted because validation of entity property values failed.
//
// T:System.NotSupportedException:
// An attempt was made to use unsupported behavior such as executing multiple asynchronous
// commands concurrently on the same context instance.
//
// T:System.ObjectDisposedException:
// The context or connection have been disposed.
//
// T:System.InvalidOperationException:
// Some error occurred attempting to process entities in the context either before
// or after sending commands to the database.
I am working on a project which deal with heavy data sets. I am using Primefaces 4 & 5, spring and hibernate. I have to to display a very huge datasets such as min 3000 rows with 100 columns with various features such as sorting, filtering, row-expansion etc. My problem is, my applications took 8 to 10 mins to show the whole page as well as other functionalities(sorting, filtering ) also takes a lot time. My client is not happy at all. However I can use pagination for this but again My client do not want paging. So I decided to use livescroll but unfortunately I failed to implement livescroll with lazyload or without lazyload as there were bugs in PF regarding livescroll. also i have posted this question here earlier but no solution found.
This performance issue is very critical and show stopper for me. To show 3000 rows with 100 columns, the size of the page which is getting loaded is ~10MB.
I have calculated the time consumed by various life-cycles of of JSF, using Phase-listener I figure out that its Browser who is taking time to parse the response rendered by jsf. To complete the all phases my application took only 25 sec.
At minimal I want to increase the performance of my project. Please share any idea, suggestion and anything which could help to overcome this problem
Note: There is no database manipulations in getters and setters as well as no complex business logic.
UPDATE :
This is my datatable without lazyload:
<p:dataTable
style="width:100%"
id="cdTable"
selection="#{controller.selectedArray}"
resizableColumns="true"
draggableColumns="true"
var="cd"
value="#{controller.cdDataModel}"
editable="true"
editMode="cell"
selectionMode="multiple"
rowSelectMode="add"
scrollable="true"
scrollHeight="650"
rowKey="#{cd.id}"
rowIndexVar="rowIndex"
styleClass="screenScrollStyle"
liveScroll="true"
scrollRows="50"
filterEvent="enter"
widgetVar="dt4"
>
Here everything is working except filtering. Once I filter then first page is displayed but unable to sort or livescroll on datatable. Note this I have tested in Primefaces5.
2nd Approch
With lazyload with same datatable
1) When I add rows="100" livescroll happens but problem with row-editing, row-expansion but filter & sorting works.
2) When I remove rows livescroll works with row-editing, row-expansion etc but filter & sorting dont work.
My LazyLoadModel is as follows
public class MyDataModel extends LazyDataModel<YData>
{
#Override
public List<YData> load(int first, int pageSize,
List<SortMeta> multiSortMeta, Map<String, Object> filters) {
System.out.println("multisort wala load");
return super.load(first, pageSize, multiSortMeta, filters);
}
/**
*
*/
private static final long serialVersionUID = 1L;
private List<YData> datasource;
public YieldRecBondDataModel() {
}
public YieldRecBondDataModel(List<YData> datasource) {
this.datasource = datasource;
}
#Override
public YData getRowData(String rowKey) {
// In a real app, a more efficient way like a query by rowKey should be
// implemented to deal with huge data
// List<YData> yList = (List<YData>) getWrappedData();
for (YData y : datasource)
{
System.out.println("datasource :"+datasource.size());
if(y.getId()!=null)
{
if (y.getId()==(new Long(rowKey)))
{
return y;
}
}
}
return null;
}
#Override
public Object getRowKey(YData y) {
return y.getId();
}
#Override
public void setRowIndex(int rowIndex) {
/*
* The following is in ancestor (LazyDataModel):
* this.rowIndex = rowIndex == -1 ? rowIndex : (rowIndex % pageSize);
*/
if (rowIndex == -1 || getPageSize() == 0) {
super.setRowIndex(-1);
}
else
super.setRowIndex(rowIndex % getPageSize());
}
#Override
public List<YData> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
List<YData> data = new ArrayList<YData>();
System.out.println("sort order : "+sortOrder);
//filter
for(YData yInfo : datasource) {
boolean match = true;
for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
String filterValue = String.valueOf(filters.get(filterProperty));
Field yField = yInfo.getClass().getDeclaredField(filterProperty);
yField.setAccessible(true);
String fieldValue = String.valueOf(yField.get(yInfo));
if(filterValue == null || fieldValue.startsWith(filterValue)) {
match = true;
}
else {
match = false;
break;
}
} catch(Exception e) {
e.printStackTrace();
match = false;
}
}
if(match) {
data.add(yInfo);
}
}
//sort
if(sortField != null) {
Collections.sort(data, new LazySorter(sortField, sortOrder));
}
int dataSize = data.size();
this.setRowCount(dataSize);
//paginate
if(dataSize > pageSize) {
try {
List<YData> subList = data.subList(first, first + pageSize);
return subList;
}
catch(IndexOutOfBoundsException e) {
return data.subList(first, first + (dataSize % pageSize));
}
}
else
return data;
}
#Override
public int getRowCount() {
// TODO Auto-generated method stub
return super.getRowCount();
}
}
I am fade up with these issues and becomes show stopper for me. Even i tried Primefaces 5
If your data is loaded from db i suggest you to do a better LazyDataModel like:
public class ElementiLazyDataModel extends LazyDataModel<T> implements Serializable {
private Service<T> abstractFacade;
public ElementiLazyDataModel(Service<T> abstractFacade) {
this.abstractFacade = abstractFacade;
}
public Service<T> getAbstractFacade() {
return abstractFacade;
}
public void setAbstractFacade(Service<T> abstractFacade) {
this.abstractFacade = abstractFacade;
}
#Override
public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
PaginatedResult<T> pr = abstractFacade.findRange(new int[]{first, first + pageSize}, sortField, sortOrder, filters);
setRowCount(new Long(pr.getTotalItems()).intValue());
return pr.getItems();
}
}
The service is some kind of backend communication (like an EJB) injected in the ManagedBean that use this model.
The service for pagination may be like this:
#Override
public PaginatedResult<T> findRange(int[] range, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
final Query query = getEntityManager().createQuery("select x from " + entityClass.getSimpleName() + " x")
.setFirstResult(range[0]).setMaxResults(range[1] - range[0] + 1);
// Add filter sort etc.
final Query queryCount = getEntityManager().createQuery("select count(x) from " + entityClass.getSimpleName() + " x");
// Add filter sort etc.
Long rowCount = (Long) queryCount.getSingleResult();
List<T> resultList = query.getResultList();
return new PaginatedResult<T>(resultList, rowCount);
}
Note that you have to do the paginated query (with jpa like this the orm do the query for you, but if you don't use orm have to do paginated query, for oracle look at TOP-N query, for example: http://oracle-base.com/articles/misc/top-n-queries.php)
Remember your return obj must be contains also the total record as a fast count:
public class PaginatedResult<T> implements Serializable {
private List<T> items;
private long totalItems;
public PaginatedResult() {
}
public PaginatedResult(List<T> items, long totalItems) {
this.items = items;
this.totalItems = totalItems;
}
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
public long getTotalItems() {
return totalItems;
}
public void setTotalItems(long totalItems) {
this.totalItems = totalItems;
}
}
All this is useful if your database table is correctly setup, pay aptention to the execution plan of the possible query and add the right index.
Hope to give some hint to improve you performance
In the end, remember to your final user that the human eyes can't see more that 10-20 record at once, so it is very useless to have thousand record in a page.
You have used the default load implementation which is used in the showcases of Primefaces. This is not the correct implementation for your case where you load your data from a database.
The load method should use the correct query with consideration of :
1) the filter fields that are used, example:
String query = "select e from Entity e where lower(e.f1) like lower('" + filters.get(key) + "'%) and..., etc. for the other fields
2) the sorting columns that are used, example:
query.append("order by ").append(sortField).append(" ").append(SortOrder.ASCENDING.name() ? "" : sortOrder.substring(0, 4)),..., etc. for the other columns.
3) The total count of your query WITH 1) attached to it. Example:
Long totalCount = (Long) entityManager.createQuery("select count(*) from Entity e where lower(e.f1) like lower('filterKey1%') and lower(e.f2) like lower('filterKey2%') ...").getSingleResult();
I am new to the dependency injection pattern and I am having issues getting a new instance of a class from container.Resolve in tinyioc it just keeps returning the same instance rather than a new instance. Now for the code
public abstract class HObjectBase : Object
{
private string _name = String.Empty;
public string Name
{
get
{
return this._name;
}
set
{
if (this._name == string.Empty && value.Length > 0 && value != String.Empty)
this._name = value;
else if (value.Length < 1 && value == String.Empty)
throw new FieldAccessException("Objects names cannot be blank");
else
throw new FieldAccessException("Once the internal name of an object has been set it cannot be changed");
}
}
private Guid _id = new Guid();
public Guid Id
{
get
{
return this._id;
}
set
{
if (this._id == new Guid())
this._id = value;
else
throw new FieldAccessException("Once the internal id of an object has been set it cannot be changed");
}
}
private HObjectBase _parent = null;
public HObjectBase Parent
{
get
{
return this._parent;
}
set
{
if (this._parent == null)
this._parent = value;
else
throw new FieldAccessException("Once the parent of an object has been set it cannot be changed");
}
}
}
public abstract class HZoneBase : HObjectBase
{
public new HObjectBase Parent
{
get
{
return base.Parent;
}
set
{
if (value == null || value.GetType() == typeof(HZoneBase))
{
base.Parent = value;
}
else
{
throw new FieldAccessException("Zones may only have other zones as parents");
}
}
}
private IHMetaDataStore _store;
public HZoneBase(IHMetaDataStore store)
{
this._store = store;
}
public void Save()
{
this._store.SaveZone(this);
}
}
And the derived class is a dummy at the moment but here it is
public class HZone : HZoneBase
{
public HZone(IHMetaDataStore store)
: base(store)
{
}
}
Now since this is meant to be an external library I have a faced class for accessing
everything
public class Hadrian
{
private TinyIoCContainer _container;
public Hadrian(IHMetaDataStore store)
{
this._container = new TinyIoCContainer();
this._container.Register(store);
this._container.AutoRegister();
}
public HZoneBase NewZone()
{
return _container.Resolve<HZoneBase>();
}
public HZoneBase GetZone(Guid id)
{
var metadataStore = this._container.Resolve<IHMetaDataStore>();
return metadataStore.GetZone(id);
}
public List<HZoneBase> ListRootZones()
{
var metadataStore = this._container.Resolve<IHMetaDataStore>();
return metadataStore.ListRootZones();
}
}
However the test is failing because the GetNewZone() method on the Hadrian class keeps returning the same instance.
Test Code
[Fact]
public void ListZones()
{
Hadrian instance = new Hadrian(new MemoryMetaDataStore());
Guid[] guids = { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
int cnt = 0;
foreach (Guid guid in guids)
{
HZone zone = (HZone)instance.NewZone();
zone.Id = guids[cnt];
zone.Name = "Testing" + cnt.ToString();
zone.Parent = null;
zone.Save();
cnt++;
}
cnt = 0;
foreach (HZone zone in instance.ListRootZones())
{
Assert.Equal(zone.Id, guids[cnt]);
Assert.Equal(zone.Name, "Testing" + cnt.ToString());
Assert.Equal(zone.Parent, null);
}
}
I know its probably something simple I'm missing with the pattern but I'm not sure, any help would be appreciated.
First, please always simplify the code to what is absolutely necessary to demonstrate the problem, but provide enough that it will actually run; I had to guess what MemoryMetaDataStore does and implement it myself to run the code.
Also, please say where and how stuff fails, to point others straight to the issue. I spent a few minues figuring out that the exception I was getting was your problem and you weren't even getting to the assertions.
That said, container.Resolve<HZoneBase>() will always return the same instance because that's how autoregistration in TinyIoC works - once an abstraction has been resolved, the same instance is always returned for subsequent calls.
To change this, add the following line to the Hadrian constructor:
this._container.Register<HZoneBase, HZone>().AsMultiInstance();
This will tell the container to create a new instance for each resolution request for HZoneBase.
Also, Bassetassen's answer about the Assert part is correct.
In general, if you want to learn DI, you should read Mark Seemann's excellent book "Dependency Injection in .NET" - not quite an easy read as the whole topic is inherently complex, but it's more than worth it and will let you get into it a few years faster than by learning it on your own.
In your assert stage you are not incrementing cnt. You are also using the actual value as the expected one in the assert. This will be confusing, becuase it says something is excpected when it actually is the actual value that is returned.
The assert part should be:
cnt = 0;
foreach (HZone zone in instance.ListRootZones())
{
Assert.Equal(guids[cnt], zone.Id);
Assert.Equal("Testing" + cnt.ToString(), zone.Name);
Assert.Equal(null, zone.Parent);
cnt++;
}
The scenario of the problem is this
1) We map the struts field values to the dtos. The dtos contain integer fields which again are displayed on the screen.
2) Now I enter an incorrect value which gives conversion error for that integer field.
3) At that point in time I decide to quit the page(i.e press cancel), I get a conversion error. This is because the StrutsConversionErrorInterceptor gets called everytime.
Is there any way that I can skip the strutsConversionErrorInterceptor when I am calling a particular method the way we can skip validation using excludeMethods
Use this code to override Struts's StrutsConversionErrorInterceptor...
public class MyConversionErrorInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
ValueStack stack = invocation.getStack();
try {
stack.push(value);
return "'" + stack.findValue("top", String.class) + "'";
} finally {
stack.pop();
}
}
#Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext invocationContext = invocation.getInvocationContext();
Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
ValueStack stack = invocationContext.getValueStack();
HashMap<Object, Object> fakie = null;
BaseAction baseAction = (BaseAction) invocation.getAction();
String buttonName = baseAction.getButtonName();
for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
if (shouldAddError(propertyName, value)) {
String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
ValidationAware va = (ValidationAware) action;
if(buttonName.equalsIgnoreCas("Next")){
va.addFieldError(propertyName, message);
}
}
if (fakie == null) {
fakie = new HashMap<Object, Object>();
}
if(buttonName.equalsIgnoreCas("Next")){
fakie.put(propertyName, getOverrideExpr(invocation, value));
}
}
}
if (fakie != null) {
// if there were some errors, put the original (fake) values in
// place right before the result
stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
if (fakie != null) {
invocation.getStack().setExprOverrides(fakie);
}
}
});
}
return invocation.invoke();
}
protected boolean shouldAddError(String propertyName, Object value) {
if (value == null) {
return false;
}
if ("".equals(value)) {
return false;
}
if (value instanceof String[]) {
String[] array = (String[]) value;
if (array.length == 0) {
return false;
}
if (array.length > 1) {
return true;
}
String str = array[0];
if ("".equals(str)) {
return false;
}
}
return true;
}
}
You can specify you button names on which you want validation to fire. In above code I have used "Next" in code you can see
if(buttonName.equalsIgnoreCas("Next"))
Yes, you can skip calling the interceptor.
Just remove the interceptor definition from your action definition in struts.xml file.
i.e., remove <interceptor-ref name="conversionError"/>
Mainly this interceptor adds any error found in the ActionContext's conversionErrors map as a field error (provided that the action implements ValidationAware). In addition, any field that contains a validation error has its original value saved such that any subsequent requests for that value return the original value rather than the value in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to the user).
After you removed this interceptor, if the struts failed to map the field with parameter of the object(i.e., from string to int), it throws result input action error.
This seems to be a better method to handle this scenario - using Conversion Validator. Repopulating Field upon conversion Error section is something very useful:
http://struts.apache.org/2.0.14/docs/conversion-validator.html