We use JDeveloper 10.1.3.4 to develop a web application. We deploy the application on OC4J running on linux. We put java code in the jsp page directly. In the jsp page, we have general java code, for example,
<% String invoice_id = ""; %>
Here the variable invoice_id is an instance variable in jsp. We also have tag such as and to handle database transactions. We have such a jsp called paymentApproved.jsp. This jsp is called by a third party gateway. In other words, the jsp is called from outside of our application. My question is, in such a scenario, is this jsp paymentApproved.jsp thread safe? I checked the translated jsp page, the class extends com.orionserver.http.OrionHttpJspPage, and the logic is in this method:
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException
Specifically, I am not sure whether an instance variable defined in such a jsp is thread safe while multiple requests coming in to call the page? Or is there anyway to test it? (I know it's a bad idea to put java code in jsp. But it's my boss's project, not mine. )Thanks
Jsp code:
<%# include file="mainHeader.jsp"%>
<%
String inv_id = "";
%>
<jbo:ApplicationModule id="AM_Payment" definition="test.AM_Payment" releasemode="Stateless" />
<jbo:DataSource id="dsinv" appid="AM_Payment" viewobject="InvoiceView1"/>
<%
SimpleDateFormat dtformat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat tmformat = new SimpleDateFormat("HH:mm:ss");
String invoicedateStr = dtformat.format(new java.util.Date());
oracle.jbo.domain.Date invoicedate = new oracle.jbo.domain.Date(invoicedateStr);
String invoicetime = tmformat.format(new java.util.Date());
inv_id = invoicedateStr+invoicetime;
%>
<BR><BR>
<table>
<tr><td>Invoice id: <%=inv_id%></td></tr>
</table>
<hr>
<%
long startTime = System.nanoTime();
int[] dummy = new int[10];
for (int i=0; i<999999999; i++) {
for (int j=0; j<10; j++) {
dummy[j] = i;
}
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
double seconds = (double)Math.round( (duration/1000000000.0d) *100.0d)/100.0d;
String sec = Double.toString(seconds);
%>
<table>
<tr><td>Invoice id: <%=inv_id%></td></tr>
<tr><td> </td></tr>
<tr><td>Process time: <%=sec%> seconds</td></tr>
</table>
<hr>
<jbo:ReleasePageResources releasemode="Stateless"/>
</body>
</html>
Leaf
<% String invoice_id = ""; %>
Here the variable invoice_id is an instance variable in jsp.
No, it's not. It's a local variable of the service method of the JSP.
is this jsp paymentApproved.jsp thread safe?
How coud we tell without seeing a single character of this JSP?
Putting Java code in a JSP is an extremely bad idea. Scriptlets shouldn't be used, for years and years. Use JSPs as pure view components, whose only role is to generate HTML markup from beans stored in te request by a controller written in Java.
Related
I want to create a page to allow users to update a mysql table. This table can be changed by client admins so I have to read the table schema and create fields on the fly. I got the basic code for doing that from How to create dynamic JSF form fields and the ajax code from How to add ajax validation to programmatically generated primefaces component.
To create a proof of concept page I use the following code (note, I'm using primefaces):
for (int idx = 1; idx < 3; idx++) {
UIInput input = new InputText();
input.setId("text" + idx);
ValueExpression targetExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(facesContext.getELContext(), "#{viewMakeFields.value}", String.class);
input.setValueExpression("value", targetExpression);
AjaxBehavior ab = new AjaxBehavior();
ab.setAsync(true);
ab.setProcess("text"+idx);
input.addClientBehavior("blur", ab); // "change" doesn't work either
form.getChildren().add(input);
}
Then, in the getter and setter, I'm getting the component ID to identify which field is changed:
public static String getCallingComponentID() {
UIComponent component = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
return component.getId();
}
public String getValue() {
String id = getCallingComponentID();
System.out.println("getValue " + id);
return text1;
}
public void setValue(String text1) {
String id = getCallingComponentID();
System.out.println("setValue " + id);
this.text1 = text1;
}
The ajax isn't firing and when I click the submit button I get (and I know mixing partial and full submits isn't good):
INFO: getValue text1
INFO: getValue text2
INFO: getValue text1
INFO: getValue text2
INFO: setValue j_id1
INFO: setValue j_id1
INFO: getValue text1
INFO: getValue text2
I see two possible solutions: get ajax working so that the component calling the setter has the correct id or get the form submit to identify which child is calling the setter. The former is preferable since I want to disable the save button until something has changed but I'm willing to accept the latter at this point. Any help would be much appreciated.
Turns out this code does work. Somewhere in my meandering the error changed and I didn't understand the significance of that. Replacing head with h:head in the xhtml file that I was adding the fields to makes ajax work.
I want to pass my query's result i.e ResultSet to JSP just for the display as i am using MVC framework.
My Servlet Code:
Connection c=Connectivity.dbConnect();
PreparedStatement ps=c.prepareStatement("select role from login where userid=? and password=?");
ps.setString(1,userid);
ps.setString(2,pass);
ResultSet rs=ps.executeQuery();
if(rs.next())
{
if(rs.getString(1).equals("admin"))
{
ps=c.prepareStatement("select * from user where userid=?");
ps.setString(1,userid);
rs=ps.executeQuery();
Result r=ResultSupport.toResult(rs);
request.setAttribute("res",r);
rs.close();
c.close();
return mapping.findForward("us");//to User.jsp
}
}
I've used ResultSupport.toResult() to forward it to JSP (forwarded by 'us' mapping) but that requires JSTL code in JSP :
User.jsp -
<c:forEach var="data" items="${requestScope.res.rows}">
<h1>${data.userid}</h1>
<h2>${data.name}</h2>
<h2>${data.password}</h2>
<h2>${data.emailid}</h2>
</c:forEach>
Moreover if i directly pass ResultSet like request.setAttribute("ResultSet",rs); i wouldn't be able to close the connection in JSP.
This Code works fine but i do NOT want to use JSTL/EL or Lists , i want to use scriplets in JSP that can handle Result or ResultSet attribute from Servlet.
You can overcome your issue like this:
1) In your database manipulation class use a POJO to add in results from ResultSet.
Contacts myContact = new Contacts();
myContact.setOffice(rs.getString("office1"));
myContact.setMail(rs.getString("xx#xx.com"));
2) Then use a List to store your results
List<Contacts> myList = new ArrayList<Contacts>();
myList.add(myContact);
3) Pass the list to your request/session Object and close ResultSet/Connection there
request.setAttribute("LIST",myList);
rs.close();
conn.close()
4) In JSP get the List and iterate over it anyway you want
ArrayList<Contacts> myList = (ArrayList<Contacts>) request.getAttribute("LIST");
for(Contacts obj: myList){
out.print(obj.getMail());
....
....
}
I want to display user's detail in a jsp. user's email, name is in one bean. which i am getting in a PagedListHolder. now i need date too which is in another bean . how can i add this date to PagedListHolder. i am using spring mvc framework
public String listUsers(Map<String, Object> map, #RequestParam(value="p", required=false) Integer p) {
PagedListHolder pagedListHolder = new PagedListHolder(usersService.listUsers());
map.put("date11", userActivity.getLastSeen_time());
int page = p;
pagedListHolder.setPage(page);
int pageSize = 2;
pagedListHolder.setPageSize(pageSize);
map.put("pagedListHolder", pagedListHolder);
System.out.println(":::::::::");
return "userListView";
}
in jsp i am using it as
<c:forEach items="${pagedListHolder.pageList}" var="user">
<tr onmouseover="ChangeColor(this, true);" onmouseout="ChangeColor(this, false);" onclick="DoNav('${pageContext.request.contextPath}/secure/detailUserView');">
<td>${user.name}</td>
<td>${user.email}</td>
<td>`DATE`</td>
</tr>
</c:forEach>
in jsp in place of DATE i need to display date which is in date bean
If the pagedListHolder stored as "pagedListHolder" in the map is available using ${pagedListHolder}, then the date, stored as "date11" in the map, must also be available using ${date11}.
You can format it using <fmt:formatDate value="{date11}"/>.
I'm trying to implement a quiz application. The application loads the questions with ajax one by one. When a user clicks the 'to next question' button his/her answer is saved in cache. But when I debug, cache list is always null...
This code creates the first cache array:
public static void viewQuiz(#Required String user, #Required String test) {
if(validation.hasErrors()) {
flash.error("Hoop kullanıcı lazım…");
index();
} else{
TestClass selectedTest = TestClass.find("title", test).first();
List<String> choiceList = new ArrayList<String>();
session.put("testID", selectedTest.id);
Cache.set("choices", choiceList, "30mn");
render();
}
}
And this code is trying to save the answers one by one:
public static void question(#Required Long id, String answer){
Long testId = Long.parseLong(session.get("testID"));
TestClass test = TestClass.findById(testId);
List<Question> questList = Question.find("test_id", test.id.intValue()).fetch();
Question quest = questList.get(id.intValue());
if(answer != null){
List<String> choiceList= Cache.get("choices",List.class);
choiceList.add(id.intValue(), answer);
Cache.set("choices", choiceList, "30mn");
}
int count = questList.size()-1;
render(quest, count, id);
}
And this code is the html view of the second:
#{extends 'main.html' /}
#{set title:'question.html' /}
<script type="text/javascript">
var questionId = ${id};
$('#nextButton').click(function(){
$('#questionDiv').html('<p><img id = "loaderGif" src="public/images/loading.gif"/></p>');
$('#questionDiv').load("/test/" + ++questionId);
});
$('#endButton').click(function(){
$('#questionDiv').html('<p><img id = "loaderGif" src="public/images/loading.gif"/></p>');
$('#questionDiv').load("/result");
});
</script>
<legend>Soru ${id+1}</legend>
<p>&{quest.question}</p>
#{list items:quest.choices, as:'choice'}
<p><input type="radio" name = "answer" id = "answer" size="30" value="${choice}"/>&{choice}</p>
#{/list}
#{if id < count}
<input id = "nextButton" name="nextButton" type="button" value="İleri"/>
#{/if}
#{else}
<input id = "endButton" name="endButton" type="button" value="Bitti"/>
#{/else}
Don't use the cache to 'store' objects. Either store it in the session or create a new model to store the answers. Generally, you cannot expect the cache to retain the objects you put into; it's a cache, not a store.
To quote from the Play! website: http://www.playframework.org/documentation/1.2.2/cache
It is important to understand that the cache contract is clear: when
you put data in a cache, you can’t expect that data to remain there
forever. In fact you shouldn’t. A cache is fast, but values expire,
and the cache generally exists only in memory (without persistent
backup).
Cache is not reliable and you may get it as null in dev mode. This is expected and you can try changing it to prod mode and see its behavior.
Caveat: This might be an inappropriate use of C#'s dynamic keyword and I probably should be using a strongly-typed view model, but...
I'm trying to avoid creating a strongly-typed view model by passing a C# 4 dynamic type to my view. I have this in my controller:
public ActionResult Index()
{
var query =
from fr in db.ForecastRates
join c in db.Codes
on
new { Code = fr.RateCode, CodeType = "ForecastRate" }
equals
new { Code = c.CodeValue, CodeType = c.CodeType }
select new
{
RateCode = fr.RateCode,
RateCodeName = c.CodeName,
Year = fr.Year,
Rate = fr.Rate,
Comment = fr.Comment
};
// Create a list of dynamic objects to form the view model
// that has prettified rate code
var forecastRates = new List<dynamic>();
foreach (var fr in query)
{
dynamic f = new ExpandoObject();
f.RateCode = fr.RateCode;
f.RateCodeName = fr.RateCodeName;
f.Year = fr.Year;
f.Rate = fr.Rate;
f.Comment = fr.Comment;
forecastRates.Add(f);
}
return View(forecastRates);
}
...and this in my view (I'm using MVC 3's Razor view engine):
#inherits System.Web.Mvc.WebViewPage<IEnumerable<dynamic>>
...
<tbody>
#foreach (var item in Model) {
<tr>
<td>#item.RateCodeName</td>
<td>#item.Year</td>
<td>#item.Rate</td>
<td>#item.Comment</td>
</tr>
}
</tbody>
I don't like how I iterate through the LINQ result to form the List of dynamic objects.
I'd like to initialize each ExpandoObject inside the LINQ query, but that doesn't seem to be supported.
I tried casting the the query result as List, but that didn't work because you can't convert anonymous type to dynamic.
Like you said, it's not supported. (I'm not saying dynamic View Models aren't supported - I'm saying what you're trying to do is not)
You could probably neaten up the LINQ query, but in the end your best bet would be to simply create a custom View Model. Seriously, it will take you about 30 seconds to do that.
I know dynamic is new and cool and everything, but your code will be a lot neater and easier to maintain if you just stick with a custom View Model in this case.
I would only go with a dynamic View Model in the very simple scenarios - most of the time you probably want to stick with what we've been doing all along - custom View Models.
Ok, you could do the following, but I wouldn't recommend it. Create a static method similar to the following
public static IHtmlString DisplayProperty(object obj, string property) {
return new HtmlString(TypeDescriptor.GetProperties(obj)[property].GetValue(obj).ToString());
}
Then in your cshtml file make the following call (make sure to using your proper namespace)
<tbody>
#foreach (var item in Model) {
<tr>
<td>#DisplayProperty(x, "RateCodeName")</td>
<td>#DisplayProperty(x, "Year")</td>
<td>#DisplayProperty(x, "Rate")</td>
<td>>#DisplayProperty(x, "Comment")</td>
</tr>
}
</tbody>
I wouldn't recommend this though but it is a solution to your problem that doesn't require a model.