الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشكلة في Jpa و Toplink على ال Glassfish

بدأه mhb300 في 11 يوليو 2008 · 8 رد · 1,646 مشاهدة · في JavaEE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

نظرا لصعوبة ترجمة المشكلة الى العربي اضطررت الى وضعها بالانجليزي

Hello everyone,

i'm runing a printing queue web service on glassfish v2, the clients ask for thier printing jobs and the server send it to them. After each successful print the client invokes a web service method to flag that certain job as being "done" so that the client will not have it sent to him again the next round when it askes for available printg jobs...

it hapens many times that the new status "done" will not persist to the data base which leads to the printing job being sent over and over again.

i tried container managed transactions and bean managed transaction with the same result. i even tried em.flush(), but no luck.....

i'm using oracle toplink..

here is how the code looks like .....

.
.
.
private void persist(Object obj){
try{ 
//ut.begin();
//em.merge(obj);
em.persist(obj);
//ut.commet();
}catch(Exception ex){
...
}
}

@webmethod
public boolean markJobAsDone(long jobID){
try{
  PrintingJob aJob = em.find(PrintingJob.class,jobID);
  aJob.setStatus("done");
  persist(aJob);
}catch(Exception ex){
   return false;
}
return true;
}

also the clients are asking for jobs every 30 seconds

another question, is there any other aproach to these queues and jobs?

i just wanted to add that i can recreate the problem simply by changing the status of a job manualy form "SQL Developer" for example from "Done" to "pending" and the job will keep beibg sent and will never be set to "Done" again....

تم تعديل هذه المشاركة بواسطة mhb300 في 11 يوليو 2008 في 00:47

أرجوا المعذرة لعدم تمكني من المشاركة بشكل مستمر لانشغالي..........

.

#2

أكتب بالعربي

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

تحياتي :)

Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why

#4

منور رامي :lol:

وادي كمان تحياتي بالعربي <_<

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#5

تحياتي لكم جميعا يا اساتذتي الكرام ................الله يعطيكم الف عافيه ....................إن شاء الله انا بستقصي عن السؤال بشكل ادق واضعه بالعربي ............ولكن مثلكم يعرف صعوبة ترجمه المصطلحات وبعض العمليات في البرمجة ..........فارجوا اعطائي مهله وسف اوافيكم بتغيير جديد إن شاء الله.....

أرجوا المعذرة لعدم تمكني من المشاركة بشكل مستمر لانشغالي..........

.

#6

نحن لم نطلب منك ترجمة المصطلحات

فقط ترجم النص الأصلي

وأبقي المصطلحات كما هي

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#7

انا صاحب الموضوع الاصلي ... طلبت من الاخ mhb3000 ان يضعه بالنيابه بسبب نسياني كلمه المرور لهذا الاسم......

المشكله باختصار كالتالي:

عندي web service شغالة على glassfish v2 الweb service مكتوبة بطريقة ال EJB 3.0 موصولة بقاعدة بيانات oracle عن طريق JPA Toplink

الweb service تعمل كـ printing server ..... برنامج الـclientي يقوم بطلب مايخصة من وظائف طباعه و الـweb server ستقوم بإرسالها له .... إذا الـclient application إستطاع اتمام الطباعة بنجاح , يرسل الى الـserver كي يغير حالة الطلب الى "done" كي لا يتم إرسالها مرة اخرى للـ client application وهنا تكمن المشكة.... ان حالة الطلب لايتم تغيرها في قاعدة البيانات ... كانما حالة الطلب تُغير في الـcache للapplication server ولا يتم مزامنتها مع قاعدة البيانات...مما ينتج عنه ان طلب الطباعة يتم إرسالة في كل مرة يقوم فيها الـclient بالاتصال بالـserver....

اتمنى ان اكون قد اوضحت السؤال...... نرجو المساعدة

#8

السلام عليكم ورحمة الله

لقد قمت بتعديل الكود حتى يقوم بالمهمة المطلوبة ،إذا لم يعمل تاكد أن الإجرائية mergeEntity تحتوي على الأمر commit

ولدي سؤال هل أنتم تعملون في السعودية إذا نعم في أي مدينة وهل أنتم بحاجة لمبرمجين J2EE خبرة في Glassfish و EJB و JPA

سلام

public void markJobAsDone(long jobID) {
	PrintingJob aJob = em.find(PrintingJob.class,jobID);
	aJob.setStatus("done");
	this.mergeEntity(aJob);
}

وما من كاتب إلا سيبلى ويبقي الدهر ما كتبت يداه

فلا تكتب بكفك غير شيء يسرك في القيامة أن تراه

#9
toad كتب:
السلام عليكم ورحمة الله

لقد قمت بتعديل الكود حتى يقوم بالمهمة المطلوبة ،إذا لم يعمل تاكد أن الإجرائية mergeEntity تحتوي على الأمر commit

ولدي سؤال هل أنتم تعملون في السعودية إذا نعم في أي مدينة وهل أنتم بحاجة لمبرمجين J2EE خبرة في Glassfish و EJB و JPA

سلام

public void markJobAsDone(long jobID) {
	PrintingJob aJob = em.find(PrintingJob.class,jobID);
	aJob.setStatus("done");
	this.mergeEntity(aJob);
}

وعليكم السلام و رحمة الله و بركاته

نعم انا من السعوديه. الشركة حاليا مايوظفون مبرمجين ..... ممكن خلال ال 9 اشهر القادمة

سبق و جربت merge و جربت ايضا container managed and bean managed transactions ومانفع...

المشكلة مفصله اكثر انقلها لك من احد مشاركاتي في منتدى اخر...... "و اسمحلى ماعندي وقت اترجمها عربي"

there is nothing on the log,

as for the code that sends the printng jobs, i have found that it actually does not look into the database to retrive the list of awaiting jobs but rather grap them from the cache. i was debuging the code, and i have found the following:

these are the 2 methods invloved:

1- PrintingJob[] getAwaitingPrintJobs(@WebParam(name = "Owner") String taskOwner)

2- boolean markJobAsDone(Long queID)

in the ideal case when there are no other operation goingon on the involved tables, everything goes according to plan.

if I change the status for a job manually inside the table then the status of that job will never be set back and it will continue to print.

this is what happenes on the server:

step 1:

method No1 gets the awaiting jobs from database, this is the query:

Query q = em.createQuery("select j from RamJobQueue j where j.taskOwner =:owner and j.queStatus =:status and (j.activity =:activity1 or j.activity =:activity2) and j.queType =:type  ");
		q.setParameter("owner", taskOwner);
		q.setParameter("status", 'W');					 // W for wainting		 P for printed
		q.setParameter("activity1", "PRINT");
		q.setParameter("activity2", "REPRINT");
		q.setParameter("type", "INVOICE");

then creates some kind of DTO to send to the client application.

step 2:

if the client printed the job succesfully, it will invok "markJobAsDone" method to flag the job as "P" for printed.

step 3: (i do this step to recreate the problem)

i go into the table and set the status of that jon back to "W" for waiting, expectedly, the job will be sent again to the client which is fine.

step 4:

the client prints the job, call "markJobAsDone" without and exceptions or errors, and it recieves "true" indecating the job as been marked to "P" for printed

step 5:

here where the strange "atleast for me" things start to happen!!

as scheduled, the client will call "getAwaintingPrintJobs" for the next round, and the method will return the same job which was supposedly marked as "P" in step 4.

when i look into the database, the status is still "W" which means step 4 like if it didn't happen. further more, when executing the query to get the awaiting jobs, the result comes back with the same print job with the status showing "P" !!?? which mean step 4 actually persisted not to the database but to the "cache" i assume. that was one point, the second one, if you look to the query, you see that i'm asking for the jobs with status = "W" ...... why on earth i get the job with a status showing "P", here is the query again

Query q = em.createQuery("select j from RamJobQueue j where j.taskOwner =:owner and j.queStatus =:status and (j.activity =:activity1 or j.activity =:activity2) and j.queType =:type  ");
		q.setParameter("owner", taskOwner);
		q.setParameter("status", 'W');					 // W for wainting		 P for printed
		q.setParameter("activity1", "PRINT");
		q.setParameter("activity2", "REPRINT");
		q.setParameter("type", "INVOICE");

after that , the job is sent avery time the client contacts the server......... this is just confusing.

here is the code for the two methods:

@WebMethod
	public PrintingJob[] getAwaitingPrintJobs(@WebParam(name = "Owner") String taskOwner){
		Query q = em.createQuery("select j from RamJobQueue j where j.taskOwner =:owner and j.queStatus =:status and (j.activity =:activity1 or j.activity =:activity2) and j.queType =:type  ");
		q.setParameter("owner", taskOwner);
		q.setParameter("status", 'W');
		q.setParameter("activity1", "PRINT");
		q.setParameter("activity2", "REPRINT");
		q.setParameter("type", "INVOICE");
		List<RamJobQueue> jobs = q.getResultList();
		PrintingJob[] pJob = new PrintingJob[jobs.size()];
		int i =0;
		for (RamJobQueue job : jobs) {
			Invoice inv = em.find(Invoice.class, Long.parseLong(job.getReferenceId()));
			TripInfo[] supportDocs = getSupportDoc(inv);
			PrintableInvoice pinv = makePrintableInvoice(inv);
			pJob = new PrintingJob(job,pinv, supportDocs,getServiceTypeInfo(inv),getCustomerInfo());
			i++;
		}
		return pJob;
	}
.
.
.
@WebMethod
	public boolean markJobAsDone(Long queID){
		try{
			BigDecimal id = BigDecimal.valueOf(queID);			
			RamJobQueue job = em.find(RamJobQueue.class, id);
			job.setQueStatus('P');
			//persist(job);
			//merge(job);
			ut.begin();
			em.merge(job);
			//em.persist(job);
			em.flush();
			ut.commit();
			em.refresh(job);
			return true;
		}catch(Exception ex){
			return false;
		}
	}

and here is the Entitiy

*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package db.jpa;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 *
 * @author XXXX
 */
@Entity
@Table(name = "RAM_JOB_QUEUE")
@NamedQueries({@NamedQuery(name = "RamJobQueue.findByQueId", query = "SELECT r FROM RamJobQueue r WHERE r.queId = :queId"), @NamedQuery(name = "RamJobQueue.findByQueType", query = "SELECT r FROM RamJobQueue r WHERE r.queType = :queType"), @NamedQuery(name = "RamJobQueue.findByReferenceId", query = "SELECT r FROM RamJobQueue r WHERE r.referenceId = :referenceId"), @NamedQuery(name = "RamJobQueue.findByActivity", query = "SELECT r FROM RamJobQueue r WHERE r.activity = :activity"), @NamedQuery(name = "RamJobQueue.findByTaskOwner", query = "SELECT r FROM RamJobQueue r WHERE r.taskOwner = :taskOwner"), @NamedQuery(name = "RamJobQueue.findByQueStatus", query = "SELECT r FROM RamJobQueue r WHERE r.queStatus = :queStatus"), @NamedQuery(name = "RamJobQueue.findByUpdatedTs", query = "SELECT r FROM RamJobQueue r WHERE r.updatedTs = :updatedTs"), @NamedQuery(name = "RamJobQueue.findByComments", query = "SELECT r FROM RamJobQueue r WHERE r.comments = :comments")})
public class RamJobQueue implements Serializable {
	private static final long serialVersionUID = 1L;
	@Id
	@Column(name = "QUE_ID", nullable = false)
	private BigDecimal queId;
	@Column(name = "QUE_TYPE")
	private String queType;
	@Column(name = "REFERENCE_ID")
	private String referenceId;
	@Column(name = "ACTIVITY")
	private String activity;
	@Column(name = "TASK_OWNER")
	private String taskOwner;
	@Column(name = "QUE_STATUS")
	private Character queStatus;
	@Column(name = "UPDATED_TS", nullable = false)
	@Temporal(TemporalType.DATE)
	private Date updatedTs;
	@Column(name = "COMMENTS")
	private String comments;

	public RamJobQueue() {
	}

	public RamJobQueue(BigDecimal queId) {
		this.queId = queId;
	}

	public RamJobQueue(BigDecimal queId, Date updatedTs) {
		this.queId = queId;
		this.updatedTs = updatedTs;
	}

	public BigDecimal getQueId() {
		return queId;
	}

	public void setQueId(BigDecimal queId) {
		this.queId = queId;
	}

	public String getQueType() {
		return queType;
	}

	public void setQueType(String queType) {
		this.queType = queType;
	}

	public String getReferenceId() {
		return referenceId;
	}

	public void setReferenceId(String referenceId) {
		this.referenceId = referenceId;
	}

	public String getActivity() {
		return activity;
	}

	public void setActivity(String activity) {
		this.activity = activity;
	}

	public String getTaskOwner() {
		return taskOwner;
	}

	public void setTaskOwner(String taskOwner) {
		this.taskOwner = taskOwner;
	}

	public Character getQueStatus() {
		return queStatus;
	}

	public void setQueStatus(Character queStatus) {
		this.queStatus = queStatus;
	}

	public Date getUpdatedTs() {
		return updatedTs;
	}

	public void setUpdatedTs(Date updatedTs) {
		this.updatedTs = updatedTs;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	@Override
	public int hashCode() {
		int hash = 0;
		hash += (queId != null ? queId.hashCode() : 0);
		return hash;
	}

	@Override
	public boolean equals(Object object) {
		// TODO: Warning - this method won't work in the case the id fields are not set
		if (!(object instanceof RamJobQueue)) {
			return false;
		}
		RamJobQueue other = (RamJobQueue) object;
		if ((this.queId == null && other.queId != null) || (this.queId != null && !this.queId.equals(other.queId))) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return ".db.jpa.RamJobQueue[queId=" + queId + "]";
	}

}

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…