Home » Eclipse Projects » EclipseLink » NullPointerException when using flush()
NullPointerException when using flush() [message #1568166] |
Fri, 16 January 2015 20:11  |
Eclipse User |
|
|
|
I am having an intermittent issue and I can't seem to nail down why it's happening. I have a EJB application that uses JPA (Eclipselink 2.3.2), which is implemented using web services. All of the beans are stateless. Every so often, when a user executes the web service responsible for refreshing information in the database, an exception is thrown. The specific line of code that causes the error to be thrown is "em.flush()". I'm hoping that someone can look at my code below, perhaps there is a problem with my implementation.
I have also seen the problem happen when I attempt to issue a remove() followed by a flush(). Any help would be much appreciated!
exception:
ERROR [com.onsemi.cim.qmserver] ClientIP=172.16.108.30, Operation=compare, Exception= [ java.lang.NullPointerException ] nulljava.lang.NullPointerException
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at org.eclipse.persistence.internal.sessions.CommitManager.sort(CommitManager.java:351)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:312)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:288)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1418)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:636)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1561)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:447)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.flush(EntityManagerWrapper.java:418)
at com.onsemi.cim.LotManager.LotManager.updateLot(LotManager.java:417)
at com.onsemi.cim.LotManager.LotManager.getLots(LotManager.java:315)
at com.onsemi.cim.qmserver.LotManagement.getLots(LotManagement.java:189)
at sun.reflect.GeneratedMethodAccessor170.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5388)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
at sun.reflect.GeneratedMethodAccessor156.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5360)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
at com.sun.ejb.containers.WebServiceInvocationHandler.invoke(WebServiceInvocationHandler.java:192)
at $Proxy247.getLots(Unknown Source)
at sun.reflect.GeneratedMethodAccessor169.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.glassfish.webservices.InvokerImpl.invoke(InvokerImpl.java:82)
at org.glassfish.webservices.EjbInvokerImpl.invoke(EjbInvokerImpl.java:82)
at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:149)
at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:94)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:116)
at org.glassfish.webservices.MonitoringPipe.process(MonitoringPipe.java:142)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:116)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:212)
at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:144)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)
at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:386)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:640)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:263)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:163)
at org.glassfish.webservices.Ejb3MessageDispatcher.handlePost(Ejb3MessageDispatcher.java:120)
at org.glassfish.webservices.Ejb3MessageDispatcher.invoke(Ejb3MessageDispatcher.java:91)
at org.glassfish.webservices.EjbWebServiceServlet.dispatchToEjbEndpoint(EjbWebServiceServlet.java:200)
at org.glassfish.webservices.EjbWebServiceServlet.service(EjbWebServiceServlet.java:131)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.doFilter(ServletAdapter.java:1059)
at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.invokeFilterChain(ServletAdapter.java:999)
at com.sun.grizzly.http.servlet.ServletAdapter.doService(ServletAdapter.java:434)
at com.sun.grizzly.http.servlet.ServletAdapter.service(ServletAdapter.java:384)
at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:179)
at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117)
at com.sun.enterprise.v3.services.impl.ContainerMapper$Hk2DispatcherCallable.call(ContainerMapper.java:354)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
This is the code that causes the error, specifically the "em.flush":
public Lot updateLot(String lotId, String stationId, String rackName, String rackPosition) throws Exception
{
//Get the current list of recipes so we can compare to the new list to get the record id's
//If there are new recipes they will be added to the table.
Lot lot = getLot(lotId);
List<LotEquipRecipe> oldLERList = lot.getLotEquipRecipes();
lot = lde.getLotData(lotId);
//reset the rackid and position
lot = setLotLocationInfo(lot,stationId,rackName,rackPosition);
String lotStatus = "";
boolean updateLotFlag = false;
try
{
if(lot.getLotStatus() != null)
lotStatus = lot.getLotStatus();
if(lotStatus.equals("RUN"))
{
//Remove the lot from the rack
removeLot(lotId, null);
//Set the log message and log to the database
String message = "Lot " + lotId + " has entered a RUN state and has been removed from rack " + stationId + "!";
dbe.saveLogEntry(stationId, "INFO", message);
//Log to the file and also set the error on the lot so that it is reported back to the client.
logger.info(message);
lot.setError("The lot is in a run state and has been removed from the rack!");
}
else
{
//Check to see if we are still in a wait state, the data may have changed if the lot was manipulated in PROMIS above.
if(lot.getLotStatus().equals("WAIT"))
{
//Check to see if lot should be re-routed and re-route it
if(processReroute(lot))
updateLotFlag = true;
//Check to see if we need to place this lot on hold
if(processRestrictedLot(lot))
updateLotFlag = true;
}
//If the lot info changed because of re-route or the lot being put on hold then update the lot info.
if(updateLotFlag == true)
lot = lde.getLotData(lotId);
//Set the lot color if the lot is supposed to go to the annex
if(lot.getAnnexFlag() == 1)
lot.setColor("191,107,255/145,0,255");
//reset the rackid and position
lot = setLotLocationInfo(lot,stationId,rackName,rackPosition);
//Identify rows
List<LotEquipRecipe> newLERList = lot.getLotEquipRecipes();
if(newLERList != null)
{
for(int x = 0; x < newLERList.size(); x++)
{
for(int y = 0; y < oldLERList.size(); y++)
{
//Only check to see if they match if neither is null to avoid nullpointerexception
if(newLERList.get(x) != null && oldLERList.get(y) != null)
{
if(newLERList.get(x).getEquipRecipeOption().equals(oldLERList.get(y).getEquipRecipeOption()))
{
newLERList.get(x).setRecordId(oldLERList.get(y).getRecordId());
}
}
}
}
}
//setLotColor(lot);
em.merge(lot);
em.flush();
}
}
catch (Exception e)
{
throw(e);
}
return lot;
}
The two entities at play here are as follows:
Lot
package com.onsemi.cim.LotManager;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
@Entity(name = "Lot")
@Table(name = "LOT")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Lot.findAll", query = "SELECT distinct l FROM Lot l left join fetch l.lotEquipRecipes")})
public class Lot implements Serializable {
@Id //Primary Key
@Column(name = "lot_id", nullable=false)
private String lotId;
@Column(name = "position")
private String lotRackPosition;
@Column(name = "hostname")
private String hostName;
// @Column(name = "recipe")
// private ArrayList<String> recipeList;
@Column(name = "lottype")
private String lotType;
@Column(name = "eqtype")
private String eqpType;
@Column(name = "wafercount")
private int waferCount;
@Column(name = "stage")
private String stageName;
@Column(name = "state")
private String state;
@Column(name = "queuetime")
private String queTime;
// @Column(name = "equipment")
// private ArrayList<String> equipRestrictList;
@Column(name = "priority")
private int lotPriority;
@Column(name = "steps")
private int stepsPerDay;
@Column(name = "status")
private String lotStatus;
@Column(name = "location")
private String promisLocation;
@Column(name = "partid")
private String partId;
@Column(name = "holdreason")
private String holdReason;
@Column(name = "color")
private String color;
@Column(name = "stepperRestr")
private String stepperRestr;
@Column(name = "error")
private String error;
@Column(name = "alphaphotomodes")
private String alphaPhotoModes;
@Column(name = "automatedrecipeid")
private String automatedRecipeId;
@Column(name = "amu")
private String amu;
@Column(name = "dispatchable")
private int dispatchable;
@Column(name = "restricted")
private int restricted;
@Column(name = "rackname")
private String rackName;
@Column(name = "expirytimer")
private String expiryTimer;
@Column(name = "stagedAt")
private String stagedAt;
@Column(name = "probecard")
private String probeCard;
@OneToMany(mappedBy="lot", orphanRemoval=true, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private List<LotEquipRecipe> lotEquipRecipes;
//Non-Database Managed Fields
@Transient
private String specRecpId;
@Transient
private int annexFlag;
@Transient
private int messageHandlingLevel;
public int getMessageHandlingLevel() {
return messageHandlingLevel;
}
public void setMessageHandlingLevel(int messageHandlingLevel) {
this.messageHandlingLevel = messageHandlingLevel;
}
public String getProbeCard() {
return probeCard;
}
public void setProbeCard(String probeCard) {
this.probeCard = probeCard;
}
public int getAnnexFlag() {
return annexFlag;
}
public void setAnnexFlag(int annexFlag) {
this.annexFlag = annexFlag;
}
public String getSpecRecpId() {
return specRecpId;
}
public void setSpecRecpId(String specRecipId) {
this.specRecpId = specRecipId;
}
public List<LotEquipRecipe> getLotEquipRecipes() {
return lotEquipRecipes;
}
public void setLotEquipRecipes(List<LotEquipRecipe> lotEquipRecipes) {
this.lotEquipRecipes = lotEquipRecipes;
}
public String getStagedAt() {
return stagedAt;
}
public void setStagedAt(String stagedAt) {
this.stagedAt = stagedAt;
}
public String getExpiryTimer() {
return expiryTimer;
}
public void setExpiryTimer(String expiryTimer) {
this.expiryTimer = expiryTimer;
}
public String getRackName() {
return rackName;
}
public void setRackName(String rackName) {
this.rackName = rackName;
}
public int getRestricted() {
return restricted;
}
public void setRestricted(int restricted) {
this.restricted = restricted;
}
public int getDispatchable() {
return dispatchable;
}
public void setDispatchable(int dispatchable) {
this.dispatchable = dispatchable;
}
public String getAmu() {
return amu;
}
public void setAmu(String amu) {
this.amu = amu;
}
public String getAutomatedRecipeId() {
return automatedRecipeId;
}
public void setAutomatedRecipeId(String automatedRecipeId) {
this.automatedRecipeId = automatedRecipeId;
}
public String getAlphaPhotoModes() {
return alphaPhotoModes;
}
public void setAlphaPhotoModes(String alphaPhotoModes) {
this.alphaPhotoModes = alphaPhotoModes;
}
public String getStepperRestr() {
return stepperRestr;
}
public void setStepperRestr(String stepperRestr) {
this.stepperRestr = stepperRestr;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getLotType() {
return lotType;
}
public void setLotType(String lotType) {
this.lotType = lotType;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getEqpType() {
return eqpType;
}
public void setEqpType(String eqpType) {
this.eqpType = eqpType;
}
public String getHoldReason() {
return holdReason;
}
public void setHoldReason(String holdReason) {
this.holdReason = holdReason;
}
public String getLotId() {
return lotId;
}
public void setLotId(String lotId) {
this.lotId = lotId;
}
public int getLotPriority() {
return lotPriority;
}
public void setLotPriority(int lotPriority) {
this.lotPriority = lotPriority;
}
public String getLotRackPosition() {
return lotRackPosition;
}
public void setLotRackPosition(String lotRackPosition) {
this.lotRackPosition = lotRackPosition;
}
public String getLotStatus() {
return lotStatus;
}
public void setLotStatus(String lotStatus) {
this.lotStatus = lotStatus;
}
public String getPartId() {
return partId;
}
public void setPartId(String partId) {
this.partId = partId;
}
public String getPromisLocation() {
return promisLocation;
}
public void setPromisLocation(String promisLocation) {
this.promisLocation = promisLocation;
}
public String getQueTime() {
return queTime;
}
public void setQueTime(String queTime) {
this.queTime = queTime;
}
public String getHostName() {
return hostName;
}
public void setHostName(String rackName) {
this.hostName = rackName;
}
public String getStageName() {
return stageName;
}
public void setStageName(String stageName) {
this.stageName = stageName;
}
public int getStepsPerDay() {
return stepsPerDay;
}
public void setStepsPerDay(int stepsPerDay) {
this.stepsPerDay = stepsPerDay;
}
public int getWaferCount() {
return waferCount;
}
public void setWaferCount(int waferCount) {
this.waferCount = waferCount;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
LotEquipRecipe
package com.onsemi.cim.LotManager;
import java.io.Serializable;
import javax.persistence.*;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
@Entity(name = "LotEquipRecipe")
@Table(name = "LOT_EQUIP_RECIPE")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "LotEquipRecipe.findAll", query = "SELECT l FROM LotEquipRecipe l"),
@NamedQuery(name = "LotEquipRecipe.findByRecordId", query = "SELECT l FROM LotEquipRecipe l WHERE l.recordId = :recordId"),
@NamedQuery(name = "LotEquipRecipe.findByLotId", query = "SELECT l FROM LotEquipRecipe l WHERE l.lotId = :lotId"),
@NamedQuery(name = "LotEquipRecipe.findByEquipRecipeOption", query = "SELECT l FROM LotEquipRecipe l WHERE l.equipRecipeOption = :equipRecipeOption")})
public class LotEquipRecipe implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "RECORD_ID")
@SequenceGenerator(name="lot_equip_recipe_seq", sequenceName="lot_equip_recipe_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="lot_equip_recipe_seq")
private Integer recordId;
@Size(max = 10)
@Column(name = "LOT_ID")
private String lotId;
@Size(max = 100)
@Column(name = "EQUIP_RECIPE_OPTION")
private String equipRecipeOption;
@ManyToOne
@JoinColumn(name="LOT_ID", insertable=false, updatable=false)
private Lot lot;
public Lot getLot() {
return lot;
}
public LotEquipRecipe() {
}
public LotEquipRecipe(Integer recordId) {
this.recordId = recordId;
}
public Integer getRecordId() {
return recordId;
}
public void setRecordId(Integer recordId) {
this.recordId = recordId;
}
public String getLotId() {
return lotId;
}
public void setLotId(String lotId) {
this.lotId = lotId;
}
public String getEquipRecipeOption() {
return equipRecipeOption;
}
public void setEquipRecipeOption(String equipRecipeOption) {
this.equipRecipeOption = equipRecipeOption;
}
@Override
public int hashCode() {
int hash = 0;
hash += (recordId != null ? recordId.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 LotEquipRecipe)) {
return false;
}
LotEquipRecipe other = (LotEquipRecipe) object;
if ((this.recordId == null && other.recordId != null) || (this.recordId != null && !this.recordId.equals(other.recordId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=" + recordId + " ]";
}
}
[Updated on: Fri, 16 January 2015 20:14] by Moderator Report message to a moderator
|
|
|
Re: NullPointerException when using flush() [message #1573337 is a reply to message #1568166] |
Mon, 19 January 2015 17:38   |
Eclipse User |
|
|
|
I spent just a few minutes looking at the code and the the NPE is coming from attempting to add an element to a TreeSet with a null key[1]. Is it possible that one of the elements that you're trying to remove doesn't have a PK set? ... I'm not sure if that makes much sense, but hopefully it'll help you narrow in on what is causing problems.
[1] :351 sortedObjects.put(objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete); // extractPrimaryKeyFromObject(...) returns null.
|
|
|
Re: NullPointerException when using flush() [message #1575332 is a reply to message #1573337] |
Tue, 20 January 2015 19:22   |
Eclipse User |
|
|
|
Thanks for the reply. I took your advice and on the exception I printed out the object that I am attempting to persist, you can see that here:
lotId=D35175.1
lotRackPosition=2,2,2
hostName=cque026x
lotType=PS
eqpType=CPDECIDE
waferCount=12
stageName=xxx
state=D
queTime=20-JAN-2015 12:12:11.00
lotPriority=5
stepsPerDay=7
lotStatus=WAIT
promisLocation=C-PHOTO
partId=xxx
holdReason=
color=null
stepperRestr=
error=null
alphaPhotoModes=null
automatedRecipeId=xxx
amu=null
dispatchable=1
restricted=0
rackName=Right Rack
expiryTimer=null
stagedAt=null
probeCard=2400
lotEquipRecipes=[com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=null ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181137 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=null ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=null ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181133 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=null ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181128 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181138 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181178 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181136 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181132 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181179 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181129 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181127 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181134 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181135 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181131 ], com.onsemi.cim.LotManager.LotEquipRecipe[ recordId=79181130 ]]
specRecpId=CPA01
annexFlag=0
messageHandlingLevel=0
serialVersionUID=2802091524634182149
_persistence_primaryKey=D35175.1
_persistence_listener=null
_persistence_fetchGroup=null
_persistence_shouldRefreshFetchGroup=false
_persistence_session=null
You can see that LotEquipRecipes has a number of items listed (This is my child table), the first two items have a null recordId, which is the primary key. This means that these records need to be added. I have a sequence setup in the database and there is a trigger setup to automatically fill that in on insert. When you issue a merge, does it expect you to be updating all records, even the child tables?
[Updated on: Tue, 20 January 2015 19:24] by Moderator Report message to a moderator
|
|
|
Re: NullPointerException when using flush() [message #1575465 is a reply to message #1575332] |
Tue, 20 January 2015 21:00   |
Eclipse User |
|
|
|
> I have a sequence setup in the database and there is a trigger setup to automatically fill that in on insert.
I don't follow your entire scenario, but this comment jumps out at me. I suspect that EclipseLink is caching the LotEquipRecipes with a null ID which then causes this problem. Try doing a refresh(or something) after the merge (on Entities with a null id) to get the L1/L2 cache(s) populated with the proper values.
> When you issue a merge, does it expect you to be updating all records, even the child tables?
When you issue a merge on a given Entity, all relationships marked as cascadeType MERGE OR ALL will also be merged.
|
|
|
Re: NullPointerException when using flush() [message #1575573 is a reply to message #1575465] |
Tue, 20 January 2015 22:29   |
Eclipse User |
|
|
|
I'm giving what you recommend a shot. I've deployed my change to production, just waiting for some data to roll in. I want to explain sort of what is going on here.
In the update function I have a the child table that I am updating, this is the basic logic.
1. get old recipe list from database and put it into variable oldLERList
2. execute function to return the new list (it may have changed).
3. loop through the new list, comparing each value to values in oldLERList, if a match is found, set the recordId in the new list to what the recordId was in the old list. (I do this so that I don't keep consuming id's each time I refresh).
4. set the lotEquipRecipes attribute in the main Lot entity.
5. merge the Lot entity.
Does this make sense? Am I over complicating this, or doing anything wrong as far as you can tell?
|
|
|
Re: NullPointerException when using flush() [message #1575836 is a reply to message #1575573] |
Wed, 21 January 2015 01:59   |
Eclipse User |
|
|
|
So after a lot of debugging and banging my head against the wall I think I figured out what was causing the problems.
The LotEquipRecipe entity uses an @GeneratedValue for the primary key. I had misunderstood how this actually worked. In the database I was using a sequence with an INSERT trigger in conjunction with the @GeneratedValue annotation. This was not the right way to go, because what was happening was Eclipselink was retrieving a value from the sequence and assigning it to the record, then when the record was inserted into the database, the trigger would grab a new record id from the sequence and apply it to the record. This confused the hell out of Eclipselink as it didn't have an accurate idea as to what the right record id was.
It's actually amazing the application worked as well as it did like this. In any case as soon as I disabled the database trigger things started working as they should. I appreciate your help on this!
|
|
| |
Goto Forum:
Current Time: Sat Feb 08 14:08:18 GMT 2025
Powered by FUDForum. Page generated in 0.03966 seconds
|