Loading all contacts using the Microsoft Graph API sometimes looses/skips pages - java

We have an application that loads all contacts stored in an account using the Microsoft Graph API. The initial call we issue is https://graph.microsoft.com/v1.0/users/{userPrincipalName}/contacts$count=true&$orderBy=displayName%20ASC&$top=100, but we use the Java JDK to do that. Then we iterate over all pages and store all loaded contacts in a Set (local cache).
We do this every 5 minutes using an account with over 3000 contacts and sometimes, the count of contacts we received due to using $count does not match the number of contacts we loaded and stored in the local cache.
Verifying the numbers manually we can say, that the count was always correct, but there are contacts missing.
We use the following code to achieve this.
public List<Contact> loadContacts() {
Set<Contact> contacts = new TreeSet<>((contact1, contact2) -> StringUtils.compare(contact1.id, contact2.id));
List<QueryOption> requestOptions = List.of(
new QueryOption("$count", true),
new QueryOption("$orderBy", "displayName ASC"),
new QueryOption("$top", 100)
);
ContactCollectionRequestBuilder pageRequestBuilder = null;
ContactCollectionRequest pageRequest;
boolean hasNextPage = true;
while (hasNextPage) {
// initialize page request
if (pageRequestBuilder == null) {
pageRequestBuilder = graphClient.users(userId).contacts();
pageRequest = pageRequestBuilder.buildRequest(requestOptions);
} else {
pageRequest = pageRequestBuilder.buildRequest();
}
// load
ContactCollectionPage contactsPage = pageRequest.get();
if (contactsPage == null) {
throw new IllegalStateException("request returned a null page");
} else {
contacts.addAll(contactsPage.getCurrentPage());
}
// handle next page
hasNextPage = contactsPage.getNextPage() != null;
if (hasNextPage) {
pageRequestBuilder = contactsPage.getNextPage();
} else if (contactsPage.getCount() != null && !Objects.equals(contactsPage.getCount(), (long) contacts.size())) {
throw new IllegalStateException(String.format("loaded %d contacts but response indicated %d contacts", contacts.size(), contactsPage.getCount()));
} else {
// done
}
}
log.info("{} contacts loaded using graph API", contacts.size());
return new ArrayList<>(contacts);
}
Initially, we did not put the loaded contacts in a Set by ID but just in a List. With the List we very often got more contacts than $count. My idea was, that there is some caching going on and some pages get fetched multiple times. Using the Set we can make sure, that we only have unique contacts in our local cache.
But using the Set, we sometimes have less contacts than $count, meaning some pages got skipped and we end up in the condition that throws the IllegalStateException.
Currently, we use microsoft-graph 5.8.0 and azure-identiy 1.4.2.
Have you experienced similar issues and can help us solve this problem?
Or do you have any idea what could be causing these inconsistent results?
Your help is very much appreciated!

Related

How can I further lower TTFB for my Spring application webpages running on Google App Engine?

I am trying to improve the speed at which pages are loading on my site and it seems the issue is with the TTFB. The backend is using Java with Spring framework.
Most of the pages on the website have a TTFB of >1000ms, this time also fluctuates and occasionally will as much as 5000ms.
I have made database indexes for all of the commonly used SQL queries in the back end as well upgrading the instance class running on Google App Engine. This has had a positive impact but the overall performance is still lacking. (The server hosting is in the nearest location to me)
Additional I observed that the TTFB is roughly 200ms longer than the time it takes for the code to run and return the model in the controller. In some cases there are a lot of attributes being added to the model so it's possible html building is taking considerable time but I wonder if there is an issue with how Spring is configured.
From what I have read online a TTFB of more than 600ms is consider sub optimal so I think there is room for more improvement.
Are there any known performance issues with Spring on Google App Engine which I should explore further?
Do you have suggestion for anything else I should try?
Below is the code from one of the slower controllers in cases that helps in identify any obvious inefficiencies.
Thanks for any help!
public String requestPrivateCompanyProfile(Model model,
#PathVariable String companyName,
#RequestParam(required = false) String alertboxMessage,
#RequestParam(required = false) String openSubmenu) {
User user = sessionService.getUser();
Ecosystem ecosystem = sessionService.getEcosystem();
model.addAttribute("user", user);
model.addAttribute("ecosystem", ecosystem);
model.addAttribute("canSeeAdminButton", accessLevelService.isUserHasManagmentAccessLevel(ecosystem, user));
model.addAttribute("userPic", cloudStorageService.getProfilePic(user));
model.addAttribute("ecoNavLogo", cloudStorageService.getEcosystemLogo(ecosystem.getName(), true));
model.addAttribute("defaultCompanyLogo",cloudStorageService.getDefaultCompanyLogo());
// Pass on the alertboxMessage and openSubmenu parameters, if there are any
if (alertboxMessage != null) model.addAttribute("alertboxMessage", alertboxMessage);
if (openSubmenu != null) model.addAttribute("openSubmenu", openSubmenu);
// If user is not registered in the current ecosystem, redirect to index
if (ecoUserDataRepository.findByKeyEcosystemAndKeyUser(ecosystem, user) == null) return "redirect:/";
// If the company doesn't exist, redirect to /companies
Company company = companyRepository.findByEcosystemAndName(ecosystem, companyName);
if (company == null) return "redirect:/companies";
//checks the user has permission to view this page
if (!accessLevelService.isCanSeePrivateCompanyProfile(ecosystem, company, user)) return "redirect:/companies";
// Store the company user data along with the profile pics of each employee
List<CompanyProfileEmployeeDto> employeeDtos = new ArrayList<>();
List<CompanyUserData> cuds = companyUserDataRepository.findAllByKeyCompany(company);
for (CompanyUserData cud : cuds) {
User employee = cud.getKey().getUser();
String profPic = cloudStorageService.getProfilePic(employee);
if (employee == company.getOwner()) {
employeeDtos.add(0, new CompanyProfileEmployeeDto(cud, profPic));
} else {
employeeDtos.add(new CompanyProfileEmployeeDto(cud, profPic));
}
}
//Get all the ecosystem users to enable search for new team members
EcoUserData[] ecoUserData = ecoUserDataRepository.findAllEcoUsers(ecosystem).toArray(new EcoUserData[0]);
//Get tags used by the company
String ecoSystemTags = ecosystem.getEcosystemTags() == null ? "" : ecosystem.getEcosystemTags();
String companyTagsString = company.getTags() == null ? "" : company.getTags();
String[] companyTags = company.getTags() == null ? null : company.getTags().replace("#", "").split(";");
List<String> unusedTags = TagsService.getUnusedTags(companyTagsString, ecoSystemTags);
//get goals and order them for the private company
List<CompanyGoal> companyGoalAchieved = companyGoalRepository.findCompanyGoalByAchievedAndCompany(false, company);
List<CompanyGoal> companyNotGoalAchieved = companyGoalRepository.findCompanyGoalByAchievedAndCompany(true, company);
Collections.reverse(companyGoalAchieved);
Collections.reverse(companyNotGoalAchieved);
//this makes achieved goals the first in the list
List<CompanyGoal> companyGoalsOrdered = new ArrayList<>(companyGoalAchieved);
companyGoalsOrdered.addAll(companyNotGoalAchieved);
//get the shared docs for a specific private company
List<CompanySharedDocs> companySharedDocs = companySharedDocsRepository.findCompanySharedDocsByCompanyAndDocType(company, "shared");
//get the admin documents for a specific private company
List<CompanySharedDocs> companyAdminDocs = companySharedDocsRepository.findCompanySharedDocsByCompanyAndDocType(company, "admin");
//get the admin documents for a specific private company
List<CompanySharedDocs> resourceLinks = companySharedDocsRepository.findCompanySharedDocsByCompanyAndDocType(company, "resource");
//gets shared notes for the company sorts the list so the recently edited notes are first in the list
List<CompanySharedNote> companySharedNotes = companySharedNoteRepository.findCompanySharedNoteByCompany(company);
companySharedNotes.sort(Comparator.comparing(CompanySharedNote::getLastEdited).reversed());
//finds all kpi associated with a company and saves them into a list, each kpi in the list then has its kpiEntries sorted by date
List<KeyPerformanceIndicator> companyKpis = keyPerformanceIndicatorRepository.findAllByCompany(company);
Collections.reverse(companyKpis);
for (KeyPerformanceIndicator kpi: companyKpis){
kpi.sortKpiEntriesByDate();
}
//checks if the user just created a new kpi and if they did add attribute to change frontend display
model.addAttribute("showKpiTab", sessionService.getAttribute("showKpiTab"));
sessionService.removeAttribute("showKpiTab");
model.addAttribute("companyKpis", companyKpis);
model.addAttribute("resourceLinks", resourceLinks);
model.addAttribute("isOwner", company.getOwner() == user);
model.addAttribute("canDeleteCompanyProfile", accessLevelService.isDeleteCompanyProfile(ecosystem, company, user));
model.addAttribute("canSeePrivateCompanyProfile", true);
model.addAttribute("canEditCompanyProfile", accessLevelService.isCanEditCompanyProfile(ecosystem, company, user));
model.addAttribute("companyAdminDocs", companyAdminDocs);
model.addAttribute("companySharedNotes", companySharedNotes);
model.addAttribute("companyGoals", companyGoalsOrdered);
model.addAttribute("companySharedDocs", companySharedDocs);
model.addAttribute("company", company);
model.addAttribute("empDtos", employeeDtos);
model.addAttribute("ecoUserData", ecoUserData);
model.addAttribute("companyTags", companyTags);
model.addAttribute("unusedTags", unusedTags);
model.addAttribute("canUploadAdminDocs", ecoUserDataRepository.findByKeyEcosystemAndKeyUser(ecosystem, user).getAccessLevels().isCanUploadAdminDocs());
model.addAttribute("companyNameList", companyUserDataRepository.findAllCompanyNameByUserAndEcosystem(user, ecosystem));
return "ecosystem/company-profile/private-company-profile";
}

Can't edit other Parse User objects , save In Background doesn't write in Parse Dashboard

I have been bonking my head everywhere on this problem , I would really need some help please !! I am pretty new to Android.
My problem is the following , I have completed the User Class with some columns , for example "Former Friends" which are a list of Strings .
I do a first query , then I find the Parseuser objects matching the query (which are not the logged in user) and then I try to fill those columns.
I also update the info for the logged in user
It properly works for the logged in user ,however I can't see the filled info for the other Parse object user
I tried modifying the write access for the first user (objects.get(0)) ,but it doesn't work
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereNotEqualTo("username", getCurrentUser().getUsername());
query.whereNotContainedIn("username",getCurrentUser().getList("Former_friends"));
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> objects, ParseException e) {
if (e == null) {
if (objects.size() > 0) {
// Here I just add the first object to a list and I update the current user data ,that works fine
List<String> aList = ParseUser.getCurrentUser().getList("Former_friends");
aList.add(objects.get(0).getString("username"));
ParseUser.getCurrentUser().put("Former_friends", aList);
ParseUser.getCurrentUser().saveInBackground();
ParseUser userfound =objects.get(0);
// The two following Lines doesn't work. I don't see "Any String" in the ParseDashboard "Name" columns..
userfound.put("Name","Any String");
userfound.saveInBackground();
There are no bugs , but no update for the non-logged-in user
Big thx,
Serge
For security reasons, in Parse Server, one user cannot change another user object directly from client side. If it were possible, a bad user could erase all other users data, for example.
So this operation requires you to write a cloud code function. You should have a cloud function similar to this one here:
Parse.cloud.define('formerFriends', async request => {
const query = new Parse.Query(Parse.User);
query.notEqualTo('username', request.user.getUsername());
query.notContainedIn('username', request.user.get('Former_friends'));
const objects = await query.find({ useMasterKey: true });
if (object.length > 0) {
const aList = request.user.get('Former_friends');
aList.add(objects[0].getUsername());
request.user.set('Former_friends', aList);
await request.user.save();
const userfound = objects[0];
userfound.set('Name', 'Any String');
await userfound.save(null, { useMasterKey: true });
}
});
And then call the cloud function from Android like this:
HashMap<String, Object> params = new HashMap<String, Object>();
ParseCloud.callFunctionInBackground("formerFriends", params, new FunctionCallback<Float>() {
void done(Object result, ParseException e) {
if (e == null) {
// success
}
}
});

In Youtube API, I get empty pages after the second page

I try to get all the live videos of youtube api at a given time.
However, after the two firsts pages that contains 50 results each, all the others pages are empty.
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/7Mn5oZUWkgMIU4kfKx7cq0D0nDI\"","items":[{THIS ONE IS OK WITH 50 RESULTS}],"kind":"youtube#searchListResponse","nextPageToken":"CDIQAA","pageInfo":{"resultsPerPage":50,"totalResults":1994},"regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/wp4SIiAGHN1uLiJgvLGoMdQoehs\"","items":[{THIS ONE IS OK TOO WITH 50 RESULTS}],"kind":"youtube#searchListResponse","nextPageToken":"CGQQAA","pageInfo":{"resultsPerPage":50,"totalResults":1994},"prevPageToken":"CDIQAQ","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/3zCHC7x--dhww0e7udfLQn3DB5Y\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CJYBEAA","pageInfo":{"resultsPerPage":50,"totalResults":1988},"prevPageToken":"CGQQAQ","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/pGfYwQfcIDdD05OBzqTVFbdg39E\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CMgBEAA","pageInfo":{"resultsPerPage":50,"totalResults":1986},"prevPageToken":"CJYBEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/qtrckZRTf7czKQNL5nQpXRu7X5A\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CPoBEAA","pageInfo":{"resultsPerPage":50,"totalResults":1985},"prevPageToken":"CMgBEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/gTY6oWopjQcy6Cuf1MGQqYGYfog\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CKwCEAA","pageInfo":{"resultsPerPage":50,"totalResults":1993},"prevPageToken":"CPoBEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/umiznrtjy7vmWkIJ5Hsm8wtU0W0\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CN4CEAA","pageInfo":{"resultsPerPage":50,"totalResults":1985},"prevPageToken":"CKwCEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/thJws1H1pJJPtOkVeq6L6VGabn8\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CJADEAA","pageInfo":{"resultsPerPage":50,"totalResults":1988},"prevPageToken":"CN4CEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/TaDYlGeeLP2H1xanLHVTtmt_DNg\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CMIDEAA","pageInfo":{"resultsPerPage":50,"totalResults":1995},"prevPageToken":"CJADEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/w3wj8nt1NHhxyh-fuWLJ1v5ncvU\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CPQDEAA","pageInfo":{"resultsPerPage":50,"totalResults":1989},"prevPageToken":"CMIDEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/r1hbVDG2ANenKRichmZxj0J2dws\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CKYEEAA","pageInfo":{"resultsPerPage":50,"totalResults":1996},"prevPageToken":"CPQDEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/hdDkPLk2aNKrJLZ8tnMnCGqhUy8\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CNgEEAA","pageInfo":{"resultsPerPage":50,"totalResults":1994},"prevPageToken":"CKYEEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/OjWuZOr5rNl_HasCmAEhF5cAN9E\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CIoFEAA","pageInfo":{"resultsPerPage":50,"totalResults":1995},"prevPageToken":"CNgEEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/g8lxb3uVDwSfamhbbxFlyoVKBTg\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CLwFEAA","pageInfo":{"resultsPerPage":50,"totalResults":1986},"prevPageToken":"CIoFEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/wnTWwe1b-0gy--2ochuizsAjD9o\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CO4FEAA","pageInfo":{"resultsPerPage":50,"totalResults":1993},"prevPageToken":"CLwFEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/N1y4dp3ngAItfwukyLLitFQFDPA\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CKAGEAA","pageInfo":{"resultsPerPage":50,"totalResults":1981},"prevPageToken":"CO4FEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/F8oNrDOjlKMvHjzPIF7cJqfK_zo\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CNIGEAA","pageInfo":{"resultsPerPage":50,"totalResults":1986},"prevPageToken":"CKAGEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/JCWNr1NCzgl0GLh66R-SHeokbW8\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CIQHEAA","pageInfo":{"resultsPerPage":50,"totalResults":1992},"prevPageToken":"CNIGEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/uTbvXolYwtv5Zt4mpLQVHCQsbF4\"","items":[],"kind":"youtube#searchListResponse","nextPageToken":"CLYHEAA","pageInfo":{"resultsPerPage":50,"totalResults":1999},"prevPageToken":"CIQHEAE","regionCode":"FR"}
{"etag":"\"7991kDR-QPaa9r0pePmDjBEa2h8/xxkZZRO_iCVgmWLAsBW4Qk6VdcU\"","items":[],"kind":"youtube#searchListResponse","pageInfo":{"resultsPerPage":50,"totalResults":1995},"prevPageToken":"CLYHEAE","regionCode":"FR"}
Here is the code used :
List<SearchResult> searchItemList = new ArrayList<>();
YouTube.Search.List searchListRequest = youTubeService.search().list("snippet");
searchListRequest.setMaxResults(NUMBER_OF_VIDEOS_RETURNED);
searchListRequest.setEventType("live");
searchListRequest.setType("video");
searchListRequest.setVideoCategoryId(GAMING_VIDEO_CATEGORY);
searchListRequest.setOrder("viewCount");
searchListRequest.setSafeSearch("none");
searchListRequest.setPrettyPrint(true);
String nextToken = "";
do {
if (!nextToken.isEmpty()) {
searchListRequest.setPageToken(nextToken);
}
SearchListResponse searchListResponse = searchListRequest.execute();
System.out.println(searchListResponse);
if (searchListResponse.getItems().size() > 0) {
searchItemList.addAll(searchListResponse.getItems());
}
nextToken = searchListResponse.getNextPageToken();
} while (nextToken != null);
I don't get why the third to last request "items" field is empty. Are there some kind of restrictions from Youtube API?

Large USN value in Evernote initial sync

I am trying to sync an evernote account using Java program, below is the code sample for it
NoteStoreClient noteStoreClient = clientFactory.createNoteStoreClient();
SyncChunk syncChunk = noteStoreClient.getSyncChunk(0, 200, true);
while (true) {
List<Note> noteListforCurrentChunk = syncChunk.getNotes();
//Sync to DB
syncChunk = noteStoreClient.getSyncChunk(syncChunk.getChunkHighUSN(), 200, true);
if (syncChunk.getChunkHighUSN() == syncChunk.getUpdateCount()) {
return;
}
}
The first call to syncChunk.getChunkHighUSN() returns 1187 for my user, which results in no notes being retrieved. This is happening to some accounts only
Can anyone help on this ?
Here's some quote on USN from the doc.
The USNs within an account start at “1” (for the first object created in the account) and then increase
monotonically every time an object is created, modified, or deleted. The server keeps track of the
“update count” for each account, which is identical to the highest USN that has been assigned.
So, the higher number of USN doesn't always mean you have many notes. It just indicates that the user has done some operations on its account.
I had to create a filter to make it working. Now i am able to retrieve all the notes under this notebook
SyncChunkFilter filter = new SyncChunkFilter();
filter.setIncludeNotes(true);
NoteStoreClient noteStoreClient = clientFactory.createNoteStoreClient();
SyncChunk syncChunk = noteStoreClient.getFilteredSyncChunk(0, 200, filter);
while (true) {
List<Note> noteListforCurrentChunk = syncChunk.getNotes();
//Sync to DB
syncChunk = noteStoreClient.getFilteredSyncChunk(syncChunk.getChunkHighUSN(), 200, filter);
if (syncChunk.getChunkHighUSN() == syncChunk.getUpdateCount()) {
return;
}
}

JavaFX - OME while storing data in HSQLDB from JSON data

I have used the HSQLDB for storing the data in my app. I make 15 Web service call one by one. and store the data in DB. It's working fine for medimum amount of data. I got the OME(Out of memory error) for large data. I mean, suppose I am having like 20k records for web service method.So we are getting the OME while storing the data into the DB. I tried with profiler feature also but I am unable to find which object was consumed more heap memory. So I struck here. I need the somebody help to solve this.
Code
try {
JSONObject jSONObject = getJSONData(clientId, ApplicationConstants.REST_METHOD_GET_ALL_CATEGORIES_LIST_BY_CLIENT_ID);
if (jSONObject != null) {
JSONArray jSONArray = jSONObject.getJSONArray(ApplicationConstants.JSON_OBJECT_RESPONSE);
Integer length = jSONArray.length();
if (length == 0) {
if (_logger.isInfoEnabled()) {
_logger.info("Categories not found for client {}", clientId);
}
} else {
if (_logger.isInfoEnabled()) {
_logger.info("{} Categories found for client {}", length, clientId);
}
SyncDao synDao = (SyncDao) getDAO(ApplicationConstants.REST_SYNC_DAO);
for (int i = 0; i < length; i++) {
JSONObject jSONObj = jSONArray.getJSONObject(i);
ProjectMenu projectMenu = new ProjectMenu();
projectMenu.setClientId(clientId);
projectMenu.setCategory(ApplicationConstants.PROJECT_MENU_CATEGORY_SUB_MENU);
projectMenu.setCategoryType(ApplicationConstants.CATEGORY_TYPE_CATEGORY);
projectMenu.setCreatedDate(jSONObj.getString(ApplicationConstants.REST_CATEGORY_CREATED_DATE));
projectMenu.setElementId(jSONObj.getString(ApplicationConstants.REST_CATEGORY_ID));
projectMenu.setIsLeaf(Boolean.FALSE);
projectMenu.setLabel(jSONObj.getString(ApplicationConstants.REST_CATEGORY_NUMBER));
projectMenu.setLevel(new Integer(4));
projectMenu.setSortOrder(jSONObj.getInt(ApplicationConstants.REST_CATEGORY_SORT_ORDER));
// Getting parent menu details
ProjectMenu parentProjectMenu = synDao.getProjectMenu(clientId,
jSONObj.getString(ApplicationConstants.REST_CATEGORY_PROJECT_COMPONENT_ID), ApplicationConstants.CATEGORY_TYPE_COMPONENT);
if (parentProjectMenu != null) {
if (ApplicationConstants.REST_NO_COMPONENT_LABEL.equalsIgnoreCase(parentProjectMenu.getLabel())) {
projectMenu.setParentMenuId(parentProjectMenu.getParentMenuId());
} else {
projectMenu.setParentMenuId(parentProjectMenu.getId());
}
projectMenu.setProjectId(parentProjectMenu.getProjectId());
}
if (_logger.isDebugEnabled()) {
_logger.debug("Persisting Category: {}", projectMenu.toString());
}
synDao.persist(projectMenu);
}
}
}
} catch (JSONException jsonex) {
if (_logger.isErrorEnabled()) {
_logger.error("Exception while synchronizing Categories.", jsonex);
}
}
Use of MEMORY tables is often the cause for OOM errors when the amount of data in the database gets larger.
Convert the tables that hold large amounts of data to CACHED tables and there won't be any more OOM errors.
SET TABLE t TYPE CACHED

Categories