I have a memory leak problem that I need to resolve it.
I have this File can help me to find the memory leak
2'777'369'064 (62.72%) [32] 8 class */planning/canvas/shared/serializable/ActionCycleSZ 0x68759f768
|- 2'777'365'536 (62.72%) [256] 35 org/apache/catalina/loader/WebappClassLoader 0x688ce9df8
| |- 2'775'589'272 (62.68%) [48] 1 java/util/HashMap 0x688ceabe0
| | |- 2'775'589'224 (62.68%) [32'784] 3'533 array of java/util/HashMap$Entry 0x689af74c0
| | |- 2'763'509'944 (62.41%) [24] 2 java/util/HashMap$Entry 0x68a0b1f98
| | | |- 2'763'509'744 (62.41%) [40] 1 org/apache/catalina/loader/ResourceEntry 0x68a0b1fb0
| | | | |- 2'763'509'704 (62.41%) [32] 41 class */gwt/server/servlet/TaProjectsSessionManager 0x68653c8e8
| | | | |- 2'763'047'360 (62.4%) [32] 6 class */selfservice/SelfConfigurator 0x6875922a0
| | | | | |- 2'763'047'328 (62.4%) [16] 2 */gwt/server/servlet/TaProjectsSessionManager$1 0x689aee328
| | | | | | |- 2'154'573'968 (48.66%) [160] 30 */impl/HRSessionImpl 0x689ee49f8
| | | | | | | |- 2'138'350'824 (48.29%) [32] 3 java/util/Collections$SynchronizedMap 0x689ee4c70
| | | | | | | | |- 2'138'350'760 (48.29%) [64] 3 org/apache/commons/collections/map/LRUMap 0x689ee5218
| | | | | | | | | |- 2'134'913'368 (48.21%) [32] 2 org/apache/commons/collections/map/AbstractLinkedMap$LinkEntry 0x68a3573d0
| | | | | | | | | |- 3'437'328 (0.08%) [2'064] 121 array of org/apache/commons/collections/map/AbstractHashedMap$HashEntry 0x68a356bc8
| | | | | | | | | |- 16 (0%) [16] 1 org/apache/commons/collections/map/AbstractHashedMap$KeySet 0x69d443088
| | | | | | | | |- 32 (0%) [16] 2 java/util/Collections$SynchronizedSet 0x69d443098
| | | | | | | | |- 2'138'350'824 (48.29%) [32] 3 java/util/Collections$SynchronizedMap 0x689ee4c70
| | | | | | | |- 16'078'096 (0.36%) [104] 19 */impl/Dictionary 0x689ee4ad8
I conclude that the class ActionCycleSZ produce the memory leak
this is ActionCycleSZ
public class ActionCycleSZ extends ActionDTO implements IsSerializable {
private CycleSZ bean;
public ActionCycleSZ() {
}
public ActionCycleSZ(Type actionType, CycleSZ bean ) {
super(actionType);
this.bean = bean;
}
public CycleSZ getBean(){
return bean;
}
public void setBean(CycleSZ bean){
this.bean = bean;
}
}
public class CycleSZ implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
String cycleLabel;
Date startDate;
Date endDate;
String startDateDTO;
String endDateDTO;
Integer numlign;
String accumulatedHours;
List<SiteSZ> listOfSites = new LinkedList<SiteSZ>();
//getter and setter
}
public class SiteSZ implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
int week;
String siteLabel;
Date startDate;
Date endDate;
String startHour;
String endHour;
String site;
String time;
String particularSlotTime;
Integer numlign;
DaySZ dayAttribute;
String accumulatedWeekHours;
Map<Util.WeekDays,DaySZ> mapAttributes = new
LinkedHashMap<Util.WeekDays,DaySZ>();
boolean workedDay; //Flag for Exceptional Canevas Entry
boolean reposHebdo;
String contratId; //contratId for Exceptional Canevas Entry
In all ActionCycleSZ I have just this Map Map mapAttributes = new
LinkedHashMap();
I think that is the problem of the leak. Do I think right? I see the code and I don't see something like a memory leak.
Can anyone help me how to detect this memory leak or give me examples of memory leak due to hashmap
Related
Using the following ANTLR grammar: https://github.com/bkiers/python3-parser/blob/master/src/main/antlr4/nl/bigo/pythonparser/Python3.g4 I want to parse from a given expression, lets say:
x.split(y, 3)
or
x + y
The variables x and y. How would I achieve this?
I tried the following approach but it seems cumbersome since I must add all build-in python functions:
Define a Listener interface
const listener = new MyPythonListener()
antlr.tree.ParseTreeWalker.DEFAULT.walk(listener, abstractTree)
Use regex + pattern matching:
const symbolicNames = ['TRUE', 'FALSE', 'NUMEBRS', 'STRING', 'LIST', 'TUPLE', 'DICTIONARY', 'INT', 'LONG', 'FLOAT', 'COMPLEX',
'BOOL', 'STR', 'INT', 'RANGE', 'NONE', 'LEN']
class MyPythonListener extends Python3Listener {
variables = []
enterExpr(ctx) {
const text = this.getElementText(ctx)
if (text && this.verifyIsVariable(text)) {
this.variables.push(text)
}
}
verifyIsVariable(leafText) {
return !leafText.includes('"') && !leafText.includes('\'') && isNaN(leafText) &&
!symbolicNames.includes(leafText.toUpperCase()) && leafText.match(/^[0-9a-zA-Z_]+$/)
}
}
I didn't look too closely at it, but after inspecting the parse tree for the Python code:
def some_method_name(some_param_name):
x.split(y, 3)
it appears that the variable names are children of the atom rule:
atom
: '(' ( yield_expr | testlist_comp )? ')'
| '[' testlist_comp? ']'
| '{' dictorsetmaker? '}'
| NAME
| number
| str+
| '...'
| NONE
| TRUE
| FALSE
;
where NAME is a variable name.
So you could do something like this:
String source = "def some_method_name(some_param_name):\n x.split(y, 3)\n";
Python3Lexer lexer = new Python3Lexer(CharStreams.fromString(source));
Python3Parser parser = new Python3Parser(new CommonTokenStream(lexer));
ParseTreeWalker.DEFAULT.walk(new Python3BaseListener() {
#Override
public void enterAtom(Python3Parser.AtomContext ctx) {
if (ctx.NAME() != null) {
System.out.println(ctx.NAME().getText());
}
}
}, parser.file_input());
which will print:
x
y
and not the method and parameter names.
Again: not thoroughly tested, I leave that for you. You can pretty print the parse tree like this:
String source = "def some_method_name(some_param_name):\n x.split(y, 3)\n";
Python3Lexer lexer = new Python3Lexer(CharStreams.fromString(source));
Python3Parser parser = new Python3Parser(new CommonTokenStream(lexer));
System.out.println(new Builder.Tree(source).toStringASCII());
to inspect for yourself where the nodes you're intereseted in occur in the parse tree. The code above will print:
'- file_input
|- stmt
| '- compound_stmt
| '- funcdef
| |- def
| |- some_method_name
| |- parameters
| | |- (
| | |- typedargslist
| | | '- tfpdef
| | | '- some_param
| | '- )
| |- :
| '- suite
| |- <NEWLINE>
| |- <INDENT>
| |- stmt
| | '- simple_stmt
| | |- small_stmt
| | | '- expr_stmt
| | | '- testlist_star_expr
| | | '- test
| | | '- or_test
| | | '- and_test
| | | '- not_test
| | | '- comparison
| | | '- star_expr
| | | '- expr
| | | '- xor_expr
| | | '- and_expr
| | | '- shift_expr
| | | '- arith_expr
| | | '- term
| | | '- factor
| | | '- power
| | | |- atom
| | | | '- x
| | | |- trailer
| | | | |- .
| | | | '- split
| | | '- trailer
| | | |- (
| | | |- arglist
| | | | |- argument
| | | | | '- test
| | | | | '- or_test
| | | | | '- and_test
| | | | | '- not_test
| | | | | '- comparison
| | | | | '- star_expr
| | | | | '- expr
| | | | | '- xor_expr
| | | | | '- and_expr
| | | | | '- shift_expr
| | | | | '- arith_expr
| | | | | '- term
| | | | | '- factor
| | | | | '- power
| | | | | '- atom
| | | | | '- y
| | | | |- ,
| | | | '- argument
| | | | '- test
| | | | '- or_test
| | | | '- and_test
| | | | '- not_test
| | | | '- comparison
| | | | '- star_expr
| | | | '- expr
| | | | '- xor_expr
| | | | '- and_expr
| | | | '- shift_expr
| | | | '- arith_expr
| | | | '- term
| | | | '- factor
| | | | '- power
| | | | '- atom
| | | | '- number
| | | | '- integer
| | | | '- 3
| | | '- )
| | '- <NEWLINE>
| '- <DEDENT>
'- <EOF>
Note that the Builder.Tree class is not part of the ANTLR library, it resides in the/my repo you linked to in your question: https://github.com/bkiers/python3-parser/blob/master/src/main/java/nl/bigo/pythonparser/Builder.java
This is the entity class for which the table would be created on cassandra database.
#Table
public class Log {
#PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private LocalDate date; //partition key
#PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.PARTITIONED)
private String name; //partition key
#PrimaryKeyColumn(ordinal = 2, type = PrimaryKeyType.PARTITIONED)
private String catagory; //partition key
#PrimaryKeyColumn(ordinal = 3, type = PrimaryKeyType.CLUSTERED)
private String timeStamp; //clustering column
private String type;
private String description;
}
The primary key is ((date,name,category),timestamp) where (date,name,category) is partition key and timestamp is clustering column.
This is the expected data when insertion would be performed
Date | name | category| timestamp | type | description |
------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.732 | short | desc1 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.735 | long | desc2 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.736 | short | desc3 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.738 | long | desc4 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.740 | short | desc5 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.741 | short | desc6 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.743 | long | desc7 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.745 | short | desc8 |
-------------------------------------------------------------------
Below data is stored in Cassandra when insertion is performed using CrudRepository's save method. Some rows are upserted. The rows with description desc3, desc5 are missing.
Date | name | category| timestamp | type | description |
------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.732 | short | desc1 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.735 | long | desc2 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.738 | long | desc4 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.741 | short | desc6 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.743 | long | desc7 |
-------------------------------------------------------------------
2017-10-11 | 201 | General | 19:51:18.745 | short | desc8 |
-------------------------------------------------------------------
Repo being used is an interface which extends CrudRepository as follows:
public interface LogRepo extends CrudRepository<Log , LocalDate>
{
...
}
Insertion code performed is as follows:
for(...){
..
logRepo.save(log); //each object is saved
..
}
Since clustering column is timestamp and is unique in this case, ideally the rows should not have been upserted. Please let know if there are anything that is missing to avoid upserting of records.
Hi I have a table parent and its fields are
mysql> select * from parent;
+----+----------+------------+-----------------------------------+---------+------+
| id | category | is_deleted | name | version | cid |
+----+----------+------------+-----------------------------------+---------+------+
| 1 | default | | Front Office | 0 | NULL |
| 2 | default | | Food And Beverage | 0 | NULL |
| 3 | default | | House Keeping | 0 | NULL |
| 4 | default | | General | 0 | NULL |
| 5 | client | | SPA | 0 | NULL |
| 7 | client | | house | 0 | NULL |
| 8 | client | | test | 0 | NULL |
| 9 | client | | ggg | 0 | 1 |
| 10 | client | | dddd | 0 | 1 |
| 11 | client | | test1 | 0 | 1 |
| 12 | client | | java | 0 | 1 |
| 13 | client | | dcfdcddd | 0 | 1 |
| 14 | client | | qqqq | 0 | 1 |
| 15 | client | | nnnnnn | 0 | 1 |
| 16 | client | | category | 0 | 1 |
| 17 | client | | sukant | 0 | 1 |
| 18 | client | | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | 0 | 1 |
I have another table parent_question
mysql> select * from parent_question;
+----+------------+---------+-----+------+
| id | is_deleted | version | pid | qid |
+----+------------+---------+-----+------+
| 1 | | 0 | 1 | 1 |
| 2 | | 0 | 1 | 2 |
| 3 | | 0 | 1 | 3 |
| 4 | | 0 | 1 | 4 |
| 5 | | 0 | 1 | 5 |
| 6 | | 0 | 1 | 6 |
| 7 | | 0 | 2 | 7 |
| 8 | | 0 | 2 | 1 |
| 9 | | 0 | 2 | 2 |
| 10 | | 0 | 2 | 8 |
| 11 | | 0 | 3 | 9 |
| 12 | | 0 | 3 | 1 |
| 13 | | 0 | 3 | 10 |
| 14 | | 0 | 3 | 11 |
| 15 | | 0 | 4 | 12 |
| 16 | | 0 | 1 | 1 |
| 17 | | 0 | 1 | 2 |
| 18 | | 0 | 1 | 3 |
| 19 | | 0 | 5 | 13 |
| 20 | | 0 | 2 | 7 |
| 21 | | 0 | 2 | 2 |
| 22 | | 0 | 1 | 14 |
| 23 | | 0 | 1 | 15 |
| 24 | | 0 | 1 | 16 |
| 25 | | 1 | 1 | 17 |
| 26 | | 0 | 1 | 21 |
| 27 | | 0 | 2 | 22 |
| 28 | | 0 | 13 | 23 |
| 29 | | 0 | 9 | 24 |
| 30 | | 0 | 12 | 25 |
| 31 | | 0 | 12 | 26 |
| 32 | | 0 | 12 | 27 |
| 33 | | 0 | 12 | 28 |
| 34 | | 0 | 14 | 29 |
| 35 | | 0 | 15 | 30 |
| 36 | | 0 | 10 | 31 |
| 37 | | 0 | 4 | 32 |
| 38 | | 0 | 16 | 33 |
| 39 | | 0 | 10 | 34 |
| 40 | | 0 | 3 | 35 |
| 41 | | 0 | 17 | 36 |
| 42 | | 0 | 1 | 37 |
| 43 | | 0 | 1 | 38 |
| 44 | | 0 | 18 | 39 |
| 45 | | 0 | 18 | 40 |
+----+------------+---------+-----+------+
45 rows in set (0.00 sec)
and this is my question table
ysql> select * from question;
----+----------+------------+------------------------------------------------------------+--
id | category | is_deleted | question | v
----+----------+------------+------------------------------------------------------------+--
1 | default | | Staff Courtesy |
2 | default | | Staff Response |
3 | default | | Check In |
4 | default | | Check Out |
5 | default | | Travel Desk |
6 | default | | Door Man |
7 | default | | Restaurant Ambiance |
8 | default | | Quality Of Food |
9 | default | | Cleanliness Of The Room |
10 | default | | Room Size |
11 | default | | Room Amenities |
12 | default | | Any Other Comments ? |
13 | client | | How is Food? |
14 | client | | test question |
15 | client | | test1 |
16 | client | | test2 |
17 | client | | test2 |
18 | client | | test2 |
19 | client | | working |
20 | client | | sss |
21 | client | | ggggg |
22 | client | | this is new question |
23 | client | | dddddddddddd |
24 | client | | ggggggggggggggggg |
25 | client | | what is a class? |
26 | client | | what is inheritance |
27 | client | | what is an object |
28 | client | | what is an abstract class? |
29 | client | | qqqq |
30 | client | | nnnn question |
31 | client | | add some |
32 | client | | general question |
33 | client | | category question |
34 | client | | hhhhhhhh |
35 | client | | this is hos |
36 | client | | gggg |
37 | client | | dddd |
38 | client | | ddddd |
39 | client | | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
40 | client | | ggg |
----+----------+------------+------------------------------------------------------------+--
what I know I have pid of parent_question table;
What I want question of question table;
for example.If I were given to find the question whose pid is 18.
So from the parent_question table I can know qid is 39 and 40 and from the question table 39 refers to bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb and 40 refers to ggg
What i tried
String queryString="SELECT distinct q FROM Question q , ParentQuestion pq ,Parent p where pq.qid.id = q.id and p.id = pq.pid.id and p.category = 'default' AND p.id = "+pid;
Query query=entityManagerUtil.getQuery(queryString);
List questionsList = query.getResultList();
return questionsList;
but it did not work.I mean I get nothing in the list.Can anybody point out my mistake.
question entity class
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
import javax.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable
#Entity
public class Question {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Version
#Column(name = "version")
private Integer version;
private String question;
private String category;
private boolean isDeleted;
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean isDeleted) {
this.isDeleted = isDeleted;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
parent entity class
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable
#Entity
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Version
#Column(name = "version")
private Integer version;
#ManyToOne
private Client cid;
public Client getCid() {
return cid;
}
public void setCid(Client cid) {
this.cid = cid;
}
private boolean isDeleted;
/* #ManyToOne
private Client cid;
public Client getCid() {
return cid;
}
public void setCid(Client cid) {
this.cid = cid;
}*/
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean isDeleted) {
this.isDeleted = isDeleted;
}
private String name;
private String category;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
Commenters are confused by your classes, and this is a good indication that you might need to think about your design. suninsky has a good point that you may not need to have an entity class call ParentQuestion (unless ParentQuestion has extra data about the relationship, of course). Here are some typical questions I would be asking.
Does every Question have a Parent? If so then there should probably be a parent property on your Question class, mapped as #ManyToOne
Does every a Parent object have a set of Questions? If yes, then the Parent object should probably have a property named questions, the type of which is some kind of collection of Question objects.
I've just setup my first Spring MVC 3 project with Hibernate 3 using Maven.
Now I'm used to having a controller-page with my controller and a model package with my models,
but with hibernate integrated what i now have is:
.
|____main
| |____java
| | |____com
| | | |____cqrify
| | | | |____tellus
| | | | | |____App.java
| | | | | |____controller
| | | | | | |____ContactController.java
| | | | | |____dao
| | | | | | |____ContactDAO.java
| | | | | | |____impl
| | | | | | | |____ContactDAOImpl.java
| | | | | |____form
| | | | | | |____Contact.java
| | | | | |____service
| | | | | | |____ContactService.java
| | | | | | |____impl
| | | | | | | |____ContactServiceImpl.java
| |____resources
| | |____config.properties
| | |____log4j.xml
| | |____Messages.properties
| | |____META-INF
| |____webapp
| | |____resources
| | | |____css
| | | |____gfx
| | | |____js
| | |____WEB-INF
| | | |____classes
| | | |____spring
| | | | |____appServlet
| | | | | |____servlet-context.xml
| | | | |____root-context.xml
| | | |____views
| | | | |____editContact.jsp
| | | | |____newContact.jsp
| | | | |____showContacts.jsp
| | | | |____includes
| | | | |____taglib_includes.jsp
| | | |____web.xml
|____test
| |____java
| |____resources
| | |____log4j.xml
|____test.txt
What I understand is that I'm to autowire "ContactService" as that is now my "model", but how do I use with with ModelAndView?
My controller
import com.cqrify.tellus.form.Contact;
import com.cqrify.tellus.service.ContactService;
#Controller
public class ContactController {
#Autowired
private ContactService contactService;
#RequestMapping(value="/")
public ModelAndView listContacts(){
Map<String, Object> contactMap;
contactMap.put("contactList", contactService.listContacts());
ModelAndView modelAndView = new ModelAndView("showContacts", "ContactService", contactMap);
return modelAndView;
}
}
As seen above
ModelAndView modelAndView = new ModelAndView("showContacts", "ContactService", contactMap);
is this right that "ContactService" will now be my modelName or have i completely missed something?
In your case you can simply return:
new ModelAndView("showContacts", "contactList", contactService.listContacts());
This means that you want to render showContacts view and the list of contacts will be available for the view under contactList name.
ContactService is a business object used to find (fetch) the model, IMHO it should not be used to name the model itself.
I am writing a forum using Spring MVC+Hibernate. Hibernate uses lazy initialization and to make it work i use OpenSessionInViewInterceptor and it works. There shouldn't be any problem with lazy initialization.
I am trying to show message tree like it is done in livejournal replies.
I DB i have only id, parentId, text columns.
mysql> select * from posts;
+----+----------+----------+----------+--------+------------+----------+
| id | threadId | authorId | parentId | text | created | modified |
+----+----------+----------+----------+--------+------------+----------+
| 1 | 5 | NULL | NULL | fda | 2011-11-24 | NULL |
| 2 | 5 | NULL | NULL | aff | 2011-11-24 | NULL |
| 3 | 5 | NULL | NULL | faee | 2011-11-24 | NULL |
| 13 | 6 | NULL | NULL | f52 | 2011-11-26 | NULL |
| 14 | 6 | NULL | 13 | c431 | 2011-11-26 | NULL |
| 15 | 6 | NULL | NULL | c31c13 | 2011-11-26 | NULL |
| 16 | 6 | NULL | 15 | n754 | 2011-11-26 | NULL |
| 23 | 4 | NULL | NULL | v52 | 2011-11-26 | NULL |
| 24 | 4 | NULL | 23 | v53 | 2011-11-26 | NULL |
| 25 | 4 | NULL | NULL | v423 | 2011-11-26 | NULL |
| 26 | 4 | NULL | 24 | v523 | 2011-11-26 | NULL |
| 27 | 4 | NULL | 23 | v253 | 2011-11-26 | NULL |
+----+----------+----------+----------+--------+------------+----------+
POJO class Post:
#Entity
#Table(name="posts")
public class Post{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
#JoinColumn(name="threadId")
private Thread thread;
#Column(name="authorId")
private Integer authorId;
#ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
#JoinColumn(name="parentId")
private Post parentPost;
#Column(name="text")
private String text;
#Column(name="created")
private Date created;
#Column(name="modified")
private Date modified;
....Many getters and setters....
}
I have written a JSP custom tag:
<custom:tree postList="${posts}"/>
posts - the list of messages for this thread.
My customTags.tld:
...
<tag>
<description>message tree</description>
<name>tree</name>
<tag-class>forum.tag.MessageTree</tag-class>
<body-content>empty</body-content>
<attribute>
<name>postList</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
...
And class for this custom tag:
public class MessageTree extends SimpleTagSupport{
private List<Post> postList;
private StringBuffer output = new StringBuffer("<ul>");
public void setPostList(List<Post> postList){
this.postList = postList;
}
public void doTag()throws JspException,IOException{
retrieveOutput(null);
output.append("</ul>");
getJspContext().getOut().print(output.toString());
}
private void retrieveOutput(Integer parentId){
int j = 0;
while(j<postList.size()){
if(parentId==null && postList.get(j).getParentPost()==null){
output.append("<li>Id: "+postList.get(j).getId());
output.append("<ul>");
//retrieveOutput(postList.get(j).getId());
output.append("</ul></li>");
}else{
if(postList.get(j).getParentPost().getId().equals(parentId)){ // !!!Here it throws java.lang.NullPointerException!!!!
output.append("<li>Id: "+postList.get(j).getId());
output.append("<ul>");
retrieveOutput(postList.get(j).getId());
output.append("</ul></li>");
}
}
j++;
}
}
}
And it throws exceptions when it is checking if(postList.get(j).getParentPost().getId().equals(parentId))
java.lang.NullPointerException
forum.tag.MessageTree.retrieveOutput(MessageTree.java:31)
forum.tag.MessageTree.retrieveOutput(MessageTree.java:28)
forum.tag.MessageTree.doTag(MessageTree.java:18)
org.apache.jsp.WEB_002dINF.jsp.showThread_jsp._jspx_meth_custom_005ftree_005f0(showThread_jsp.java:457)
org.apache.jsp.WEB_002dINF.jsp.showThread_jsp._jspService(showThread_jsp.java:239)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:389)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
But when I try, for example,
public void doTag()throws JspException,IOException{
output.append(postList.get(1).getParentPost().getId());
getJspContext().getOut().print(output.toString());
}
It works and it retrieves 23!
May be I am doing it absolutely incorrect? What can you advice?
Ye, I have found errors! I have rewritten it a little bit. The problem was that I didn't check in the else-clause whether the object has the parrent post or not.
private void retrieveOutput(Integer parentId){
int j = 0;
while(j<postList.size()){
if(parentId==null && postList.get(j).getParentPost()==null){
output.append("<li>Id: "+postList.get(j).getId()+"<br/>ParentId: 0<br/>Text: "+postList.get(j).getText()+"<br/>Posted: "+postList.get(j).getCreated()+"<br/>Delete this shit");
output.append("<ul>");
retrieveOutput(postList.get(j).getId());
output.append("</ul></li>");
}else{
if(postList.get(j).getParentPost()!=null && postList.get(j).getParentPost().getId().equals(parentId)){
output.append("<li>Id: "+postList.get(j).getId()+"<br/>ParentId: "+postList.get(j).getParentPost().getId()+"<br/>Text: "+postList.get(j).getText()+"<br/>Posted: "+postList.get(j).getCreated()+"<br/>Delete this shit");
output.append("<ul>");
retrieveOutput(postList.get(j).getId());
output.append("</ul></li>");
}
}
j++;
}
}
I think your problem is with Lazy fetching you can't access a lazy fetched property outside a transaction check this link.