In my JSP page, I am iterating over a list of objects using the c:forEach tag. Each object in this iteration has a name field, and I am trying to use that name field to reference other objects that I have added to my Spring model. However, when I do this, I am getting an exception saying the property of the second object cannot be found on a String. Let me illustrate with a simplified example.
<c:forEach items="${companyList}" var="company" varStatus="num">
<c:set var="monthStats" value="${company.name}_month" />
<tr>
<td>Properties This Month</td>
<td>${monthStats.properties}</td>
</tr>
....
</c:forEach>
All of the objects are located inside a Spring Model object and have been set like this
model.addAttribute(company.getName() +"_month", currentMonthStats);
I have also tried throwing out the <c:set tag and trying
${(company.name + "_month").properties}
as well as
${${company.name + "_month"}.properties}.
Those havent worked either. Also, I wasn't quite sure how to word my title, so if it could worded better let me know so that other people can find this if they have the same issue.
You're basically asking for double-evaluation, and it doesn't work like that.
I'd modify the data delivered to the view layer to be something a little less odd, so you can access it in a non-pathological manner, like by putting the month stats into a map accessed by the company name (or id), or directly associated them in a DTO, etc.
Related
I have a UI macro that fetches a list of records and displays them into a table above some form fields. I'm not using an embedded list because I want the table to read-only and so far, haven't found a way to make an embedded list read.
In my macro I have :
<g2:evaluate var="jvar_records" object="true" >
var gr = new GlideRecord(Tables.PTC);
gr.query();
gr;
</g2:evaluate>
<j2:while test="$[jvar_records.next()]">
<tr class="$[jvar_class]">
<td>$[jvar_records.getValue('arrival_date')]</td>
<td>$[jvar_records.getValue('departure_date')]</td>
<td>$[jvar_records.getDisplayValue('certifier')]</td>
<td>$[jvar_records.getDispalayValue('trip.depart_reason_code')]</td>
</tr>
</j2:while>
The field certifier and trip are Reference fields, that I want to get the dispaly value of. But they keep coming back as empty in the macro. It works in a background-script just fine.
If I just get the value jvar_records.getValue('certifier') it correctly gives me the sys_id.
What am I missing?
Am relatively certain that, outside of the <g2: evaluate> tag, Jelly is constrained to client side API. Client side GlideRecord doesn't have a getDisplayValue function.
What I would do is have your g2:evaluate actually loop through the records and build an array of normal JavaScript objects with just the values you will need, then return that array of objects as opposed to returning the GlideRecord object with query results.
In Thymeleaf we can do the following - we all know this:
<tr th:fragment="contacts" th:each="contact,rowStat : ${person.contactList}">
<td th:text="${rowStat.count}">count</td>
<td><input type="hidden" th:field="${person.contactList[__${rowStat.index}__].id}">
</tr>
Question:
What data type is there in "rowStat.count"?
I tried to find different alphabet combination over google to find it but couldnt find anything related to it. Why I am asking this is as it shows as 1,2,3,... on the view and at the same time seems very lucrative phenomenon as it fits my requirement of using it as Integer (if it is Integer, Big "IF") and want to consume it by assigning it to on my entity's Integer field.
Am I thinking in right direction? I mean if it is Integer type, is it a good idea to use it with Spring Data JPA?
Any pointers or information in this regard will be truly helpful.
I am trying to load all the Dish objects. Dish and DishImages have a one-to-many relationship i.e. a Dish can have many DishImages associated with it.
Here is the code for both the classes.
Dish
DishImage
This is how I am trying to retrieve it in action method:
[ChildActionOnly]
public PartialViewResult TopDishes()
{
IEnumerable<Dish> topDishes = dishRepository.Dishes.Include( d => d.DishImages );
return PartialView(topDishes);
}
Here is the code for view:
#model IEnumerable<RestaurantHub.Domain.Entities.Dish>
#foreach (var dish in Model)
{
<div class="top-ten-offers-list">
<div class="top-ten-offer">
<p class="top-ten-deal-description">
#dish.Description
</p>
<img src="#dish.DishImages.First().ImagePath" />
<p class="top-ten-deal-title">#dish.Name</p>
</div>
</div>
}
I have read several SO questions most of them suggest using Include() (which I am doing), others suggest setting MARS to true. I believe I'm missing some subtle point here. Any help is appreciated.
Debug info:
If I debug the code upto the action method I can verify (by enumerating the results) that correct data is being loaded. But when the control reaches foreach loop in the view it throws the mentioned error.
If I remove the line #dish.DishImages.First().ImagePath from view it works fine, though I don't get any images.
That's because you have multiple queries at same time:
... When Code First creates a connection by
convention, which it has been in our examples, it will enable MARS. If you are supplying
your own connection, you will need to ensure that MARS is enabled if you want to be
able to have multiple active queries.
If you don’t enable MARS and your code tries to run two active queries, you will receive
an exception. The exception you receive will depend on the operation that triggers the
second query, but the inner exception will be an InvalidOperationException stating
“There is already an open DataReader associated with this Command which must be
closed first.” - from Julia Lerman's Programming EF DbContext
It seems that you've created your own Connection for EF in the web.config. If so, you should add MultipleActiveResultSets=True; to its connectionString property:
<add name="..." connectionString="metadata=res:...;provider=System.Data.SqlClient;provider connection string="data source=... ;
MultipleActiveResultSets=True; //Add this
App=EntityFramework"" providerName="System.Data.EntityClient" />
Update:
In fact, the problem is from your view. the <img src="#dish.DishImages.First().ImagePath" /> line causes that exception. You ask why?! I'll tell you why:
First of all, you performed a query on your db:
IEnumerable<Dish> topDishes = dishRepository.Dishes.Include( d => d.DishImages );
return PartialView(topDishes);
However, in fact you didn't perform any query! you just created an IEnumerable collection (That's because you didn't call .ToList(), .AsEnumerable(), etc.) and this isn't a problem.
So you pass a collection to your view. The first query performs in your foreach loop - OK, still no problem...
Until we get to the img tag: <img src="#dish.DishImages.First().ImagePath" />. This (#dish.DishImages.First()) performs a new query to db --> the problem!
Solution:
I don't know that calling .ToList() in your controller solve your problem or not - maybe. However your current EF connection string MUST have the MultipleActiveResultSets=True; property to work correctly in these situations.
Are there any good reasons why you are using an IEnumerable and don't materialize your collection to List/Array? I think your problem would dissapear, if you would get all the results to memory (ToList()/ToArray()) and then hand them over to your view where you could manipulate the in-memory collection however you see fit.
I have a application which allows user to make a search.
Based on the search criteria entered, a service call to DAO function is made (pattern jsp event -> interceptors -> processors -> services -> DAO -> database) and list of results is returned back which gets displayed in myView.jsp
Code as below is used to read the TO data in JSP:
<jsp:usebean id="myTO" type="com.myPackage.MyTO" scope="session"/>
and in the body something like
<%= myTo.getSomething() =%>
Each item on the list is clickable for details. So on clicking item 2 on the list, another call will be made with item 2's id to fetch more details on item 2.
Depending on type of item, the details are fetched in different TO's. e.g. Type1TO, Type2TO.
So detailed data on item is returned in one such TO.
Issue is: I am displaying the details in the same JSP. So the returnURL of the second request gets forwarded to myView.JSP
So I have put a line like
<jsp:usebean id="type1TO" type="com.myPackage.Type1TO" scope="session"/>
However this gives error during the first call of list search when above Type1TO does not yet exist. Error is something like "unable to find type1TO in scope session"
How could I solve this issue ???
Is there a way to put jsp:usebean tag in an if condition in the place where it is to be used in the body ?? Or any other solution to this ??
I am new to JSP and dealing with legacy JSP. So very advanced JSP (complex EL) might not be feasible.
The following are the usages of the <usebean>:
<jsp:useBean id=”connection” class=”com.myco.myapp.Connection” /> . In this example the bean with the id is made available either by creating or finding the existing one in the session
<jsp:useBean id=”connection” class=”com.myco.myapp.Connection”>
<jsp:setProperty name=”connection” property=”timeout” value=”33”>
</jsp:useBean>. In this example, the bean is created or found, and instatiated with the setProperty if it is being created.
<jsp:useBean id=”wombat” type=”my.WombatType” scope=”session”/>. In this example the existing bean is found and made available with the given type.
If translated to Servlet, your first code snippet will look like:
getAttribute("myTO");
Whether to use a single attribute or 'multiple attributes with if-else logic' depends on your particular case. Without understanding your particular situation, I can see the following options:
Option 1
Wherever you are setting myTO attribute, ensure you set the value to the same variable, so that you don't have to use if-else logic in jsp.
Option 2
Use scripts
<%
com.myPackage.MyTO toObject = session.getAttribute("myTo");
if (toObject == NULL) {
toObject = session.getAttrbute("type1TO");
}
%>
I have a need to do something like this:
bob.common=goat
bob.have=I have a {bob.common}!
bob.want=I want a {bob.common}!
bob.need=I need a {bob.common}!
Is this sort of thing possible? I know this seems silly, but being able to re-use a common piece is a need here, and we really can't (don't want to) do it programmatically.
We're already using numbered arguments in our properties, but we would like to be able to pass in a reference to another property.
I suggest to do this :
bob.common=goat
bob.have=I have a {0}!
bob.want=I want a {0}!
bob.need=I need a {0}!
Then in your page :
<spring:message code="bob.common" var="animal"/>
<spring:message code="bob.have" arguments="${animal}"/>
<spring:message code="bob.want" arguments="${animal}"/>
<spring:message code="bob.need" arguments="${animal}"/>
The way you want to do would be too strict, if you want to change your animal for example.
According to the Spring changelog, this has been supported since 2.5.3:
PropertyPlaceholderConfigurer supports nested keys in placeholder keys as well (e.g. "${db.${environment}}")
So for your example case, you should be able to use:
bob.have=I have a ${bob.common}!
and the PropertyPlaceholderConfigurer should recognise the "nested key" and resolve that correctly.