3
    Laerer laerer = (Laerer) session.getAttribute("laererInnlogget");
    List<Spoerreskjema> ss = laerer.getSkjemaliste();

    if(ss == null)
        System.out.println("1");
    if(ss != null)
        System.out.println("2");
    if(ss.isEmpty())
        System.out.println("3");
    if(!ss.isEmpty())
        System.out.println("4");

The if-loops are there to show what the problem is.

The console will show 2, and then throw a NullPointerException upon reaching ss.isEmpty()

The laerer object is not null, but contains a List which should be null (or atleast empty)

All of this is stored, and fetched in/from a postgresql database.

Any idea what the problem could be?

Btw, calling ss.size() will also cause NullPointerException

I essentially want to be able to check if the list is empty, or not.

SEVERE: Servlet.service() for servlet [no.hib.prosjekt01.controllers.laerer.LaererHjemServlet] in context with path [/prosjekt01] threw exception
java.lang.NullPointerException
    at org.apache.openjpa.enhance.no$hib$prosjekt01$models$Laerer$pcsubclass.pcReplaceField(Unknown Source)
    at org.apache.openjpa.kernel.StateManagerImpl.replaceField(StateManagerImpl.java:3254)
    at org.apache.openjpa.kernel.StateManagerImpl.storeObjectField(StateManagerImpl.java:2681)
    at org.apache.openjpa.kernel.StateManagerImpl.storeObject(StateManagerImpl.java:2671)
    at org.apache.openjpa.jdbc.meta.strats.StoreCollectionFieldStrategy.load(StoreCollectionFieldStrategy.java:596)
    at org.apache.openjpa.jdbc.meta.FieldMapping.load(FieldMapping.java:934)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.load(JDBCStoreManager.java:681)
    at org.apache.openjpa.kernel.DelegatingStoreManager.load(DelegatingStoreManager.java:117)
    at org.apache.openjpa.kernel.ROPStoreManager.load(ROPStoreManager.java:78)
    at org.apache.openjpa.kernel.StateManagerImpl.loadFields(StateManagerImpl.java:3146)
    at org.apache.openjpa.kernel.StateManagerImpl.loadField(StateManagerImpl.java:3226)
    at org.apache.openjpa.kernel.StateManagerImpl.fetchObjectField(StateManagerImpl.java:2468)
    at org.apache.openjpa.kernel.StateManagerImpl.fetchField(StateManagerImpl.java:890)
    at org.apache.openjpa.kernel.StateManagerImpl.fetch(StateManagerImpl.java:852)
    at org.apache.openjpa.enhance.RedefinitionHelper$1.invoke(RedefinitionHelper.java:230)
    at com.sun.proxy.$Proxy68.isEmpty(Unknown Source)
    at no.hib.prosjekt01.controllers.laerer.LaererHjemServlet.doGet(LaererHjemServlet.java:35)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

Edit1:

Creating subclass for "[class no.hib.prosjekt01.models.Spoerreskjema, class no.hib.prosjekt01.models.Laerer, class no.hib.prosjekt01.models.Svar, class no.hib.prosjekt01.models.Spoersmaal, class no.hib.prosjekt01.models.Kryptering]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.

Edit2:

@Entity
@Table(name = "laerer")
public class Laerer implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private String id;
private String fornavn;
private String etternavn;
@Lob
private byte[] passord;

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "laerer")
private List<Spoerreskjema> skjemaliste;



public Laerer(String epost, String fornavn, String etternavn, byte[] passord) {
    this.id = epost;
    this.fornavn = fornavn;
    this.etternavn = etternavn;
    this.passord = passord;
    this.skjemaliste = new ArrayList<Spoerreskjema>();
}

public Laerer() {
    id = null;
    fornavn = null;
    etternavn = null;
    passord = null;
    skjemaliste = null;
}
Patidati
  • 1,048
  • 2
  • 12
  • 19
  • Well maybe the object you get is of a class with such a strange implementation of isEmpty method. – Nailgun Nov 10 '14 at 10:45
  • 1
    Try printing `laerer.getSkjemaliste().isEmpty()' directly, what is printed? You should try adding a break point and check the ss type. – Pintouch Nov 10 '14 at 10:45
  • 2
    whats the return type of laerer.getSkjemaliste() – Nirav Prajapati Nov 10 '14 at 10:46
  • @Pintouch Still gives me a nullpointer exception – Patidati Nov 10 '14 at 10:47
  • @Nailgun the isEmpty method is from the api – Patidati Nov 10 '14 at 10:48
  • @NiravPrajapati it is List – Patidati Nov 10 '14 at 10:48
  • @Patidati `List` is just an interface. What is the class of your object? – Nailgun Nov 10 '14 at 10:48
  • 3
    Please use a debugger and check out of which implementation your list is. When you are using an ORM Framework for example, most lists are based on proxi objects which tries to load your data lazy. So when you access your list outside of your database transaction, strange behaviors are normal ;) So inspect your list impl. look up the API for this to handle it correctly. – Rene M. Nov 10 '14 at 10:49
  • @MarounMaroun I don't use it here to illustrate a point :) If the console wrote 1, i would expect a nullpointer exception, but since it writes 2 i shouldnt get one – Patidati Nov 10 '14 at 10:49
  • Try breaking on the first if statement, and check ss object – Pintouch Nov 10 '14 at 10:49
  • @rmertins I actually am loading this data lazy, could that be the problem? If so, could you point me in the correct direction by any chance :)? – Patidati Nov 10 '14 at 10:52
  • What ORM are you using, where are your transaction borders? How does the instance of your list look in the debugger after: laerer.getSkjemaliste(); ? – Rene M. Nov 10 '14 at 10:53
  • @rmertins Using postgresql, not sure what you mean with transaction borders :) Added something in the description, if that helps? – Patidati Nov 10 '14 at 11:01
  • my guts feeling is telling me something else is throwing exception somewhere else in you program. isEmpty() method should not throw NullPointException. unless ur list is empty to begin with. – nafas Nov 10 '14 at 11:05
  • I see it is a servelet so you are in a webaplication using openJPA as ORM. Also it says that your ORM is loading one2one and one2many relations eager. This means the list (if it is one2many) should already be loaded. The problem now can only exist in the list implementation of openJPA. – Rene M. Nov 10 '14 at 11:09
  • Are you sure that this where exception is occurring. It could occur somewhere else in another thread, coincidentally display when you reach `ss.isEmpty()`. – Niroshan Nov 10 '14 at 11:10
  • Transaction borders, means the definition from thet start of an database transaction till the end. In an application using jpa for example you can spread a transaction over several database calls to handle for example lazy loading. – Rene M. Nov 10 '14 at 11:11
  • I have narrowed this down to this :) The problem originally was in a jsp. It is the usage of the list that is causing the error. – Patidati Nov 10 '14 at 11:11
  • @rmertins yes that's correct, this is in a servlet:) You say the problem can only exist in the list implementation of openJPA... what now? Any idea what I could do to try to fix this? – Patidati Nov 10 '14 at 11:14
  • Can you add your Laerer class with JPA annotations in your question? – Pintouch Nov 10 '14 at 11:14
  • @Patidati just out of curiosity mate. could you put a print out before your if statements (e.g. here1).and put a print out right at the end(e.g. here2) and see if it print "here1" and "here2" at all? – nafas Nov 10 '14 at 11:14
  • So after some reachare and this line: com.sun.proxy.$Proxy68.isEmpty(Unknown Source) after a doGet() shows me that you access the list after his transaction. Try to get the size of the list in your DAO Object after the query execute. Before you return the Laerer Object. The I just saw that you getting the Laerer object from the session. There it is always out of the database transaction. – Rene M. Nov 10 '14 at 11:16
  • I think that you're facing this problem : http://stackoverflow.com/questions/6864574/openjpa-lazy-fetching-does-not-work?rq=1 . You have to re-attach the context of the query to fetch the list – Pintouch Nov 10 '14 at 11:20
  • @rmertins I'm using getSingleResult, and handling it if it should return null. This is handled a good while before this error has the potential to occur – Patidati Nov 10 '14 at 11:22

1 Answers1

5

OK now I have it. You are loading the Laerer Object and then placing it in the session. Somewhere later you try to access a lazy loaded collection on it. But the problem is, that the proxy inside of your list, which should call your database to get the data, needs to be in the same transaction as your call to the database when you loaded Laerer.

There a several solutions.

  1. When you know that there are not so many objects in that list change to "EAGER" and you are happy.

  2. In your DAO after you got the Laerer Object from the entitymanager call the list to load it. Same as loading it directly "EAGER". (JPA defines that an entity can only have one EAGER Loaded list)

  3. Don't load directly the list. Instead load the list of IDs when loading Laerer Object. When you then access the list of ids over the session you can call the database again to load the required objects by IDs. For example you can place the list of IDs as a comma seperated string in a transient variable of your entity. This string can directly be use in an SELECT a FROM a.class WHERE a.id IN (:IDS) Query.

Rene M.
  • 2,660
  • 15
  • 24