Commit a87bb1ae authored by Piotr Gawron's avatar Piotr Gawron
Browse files

project errors and warnings extracted and moved to separate table

parent 6ce765c9
......@@ -7,12 +7,9 @@ import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.OrderBy;
import org.apache.logging.log4j.core.LogEvent;
import org.hibernate.annotations.*;
import org.hibernate.annotations.CascadeType;
import lcsb.mapviewer.common.MinervaLoggerAppender;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.cache.UploadedFileEntry;
import lcsb.mapviewer.model.graphics.MapCanvasType;
import lcsb.mapviewer.model.map.MiriamData;
......@@ -61,10 +58,9 @@ public class Project implements Serializable {
*/
private double progress = 0;
private String errors = null;
@Column(columnDefinition = "TEXT")
private String warnings;
@Cascade({ CascadeType.ALL })
@OneToMany(mappedBy = "project", orphanRemoval = true)
private Set<ProjectLogEntry> logEntries = new HashSet<>();
@Enumerated(EnumType.STRING)
private MapCanvasType mapCanvasType = MapCanvasType.OPEN_LAYERS;
......@@ -171,14 +167,6 @@ public class Project implements Serializable {
this.models = models;
}
public String getErrors() {
return errors;
}
public void setErrors(String errors) {
this.errors = errors;
}
public String getDirectory() {
return directory;
}
......@@ -211,62 +199,6 @@ public class Project implements Serializable {
this.organism = organism;
}
public void addWarning(String warning) {
if (warning.trim().contains("\n")) {
throw new InvalidArgumentException("Warning must be one line of text");
}
if (warning.trim().equals("")) {
return;
}
if (warnings == null) {
warnings = warning.trim();
} else {
warnings = warnings + "\n" + warning.trim();
}
}
public List<String> getWarnings() {
List<String> result = new ArrayList<>();
if (warnings == null) {
return result;
}
String[] warningsArray = warnings.split("\n");
for (String string : warningsArray) {
result.add(string);
}
return result;
}
public void addWarnings(List<String> warnings) {
StringBuilder sb = new StringBuilder("");
if (this.warnings != null) {
sb.append(this.warnings);
}
for (String string : warnings) {
if (string.trim().equals("")) {
continue;
}
if (string.contains("\n")) {
throw new InvalidArgumentException("Warning must be one line of text, but found:\n" + string);
}
if (sb.length() > 0) {
sb.append("\n");
}
sb.append(string.trim());
}
if (sb.length() != 0) {
this.warnings = sb.toString();
}
}
public void addLoggingInfo(MinervaLoggerAppender appender) {
List<String> warnings = new ArrayList<>();
for (LogEvent event : appender.getWarnings()) {
warnings.add(event.getMessage().getFormattedMessage().replaceAll("\n", "_NEW_LINE_"));
}
addWarnings(warnings);
}
public boolean isSbgnFormat() {
return sbgnFormat;
}
......@@ -400,4 +332,24 @@ public class Project implements Serializable {
this.owner = owner;
}
public Set<ProjectLogEntry> getLogEntries() {
return logEntries;
}
public void setLogEntries(Set<ProjectLogEntry> logEntries) {
this.logEntries = logEntries;
}
public void addLogEntry(ProjectLogEntry entry) {
logEntries.add(entry);
entry.setProject(this);
}
public void addLogEntries(Set<ProjectLogEntry> createLogEntries) {
for (ProjectLogEntry projectLogEntry : createLogEntries) {
addLogEntry(projectLogEntry);
}
}
}
package lcsb.mapviewer.model;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class ProjectLogEntry implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(optional = false)
private Project project;
@Column(nullable = false)
private String severity;
@Column(nullable = false)
private String type;
private String objectIdentifier;
private String objectClass;
private String mapName;
@Column(nullable = false)
private String content;
public ProjectLogEntry() {
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getMapName() {
return mapName;
}
public void setMapName(String mapName) {
this.mapName = mapName;
}
public String getObjectClass() {
return objectClass;
}
public void setObjectClass(String objectClass) {
this.objectClass = objectClass;
}
public String getObjectIdentifier() {
return objectIdentifier;
}
public void setObjectIdentifier(String objectIdentifier) {
this.objectIdentifier = objectIdentifier;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
......@@ -12,8 +12,6 @@ import org.junit.*;
import lcsb.mapviewer.ModelTestFunctions;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.common.MinervaLoggerAppender;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.model.cache.UploadedFileEntry;
import lcsb.mapviewer.model.map.MiriamData;
import lcsb.mapviewer.model.map.model.*;
......@@ -89,9 +87,6 @@ public class ProjectTest extends ModelTestFunctions {
project.setModels(models);
assertEquals(models, project.getModels());
project.setErrors(errors);
assertEquals(errors, project.getErrors());
project.setDirectory(directory);
assertEquals(directory, project.getDirectory());
......@@ -117,80 +112,4 @@ public class ProjectTest extends ModelTestFunctions {
assertEquals(creationDate, project.getCreationDate());
}
@Test(expected = InvalidArgumentException.class)
public void testAddCreationWarning() {
Project md = new Project();
md.addWarning("text\ntext");
}
@Test
public void testAddCreationWarning2() {
Project md = new Project();
md.addWarning("");
List<String> warnings = md.getWarnings();
assertEquals(0, warnings.size());
}
@Test
public void testAddCreationWarning3() {
Project md = new Project();
md.addWarning("xqw");
List<String> warnings = md.getWarnings();
assertEquals(1, warnings.size());
assertEquals("xqw", warnings.get(0));
md.addWarning("WER");
warnings = md.getWarnings();
assertEquals(2, warnings.size());
assertEquals("WER", warnings.get(1));
}
@Test
public void testAddCreationWarnings() {
List<String> warnings = new ArrayList<>();
warnings.add("xqw");
warnings.add("aso");
warnings.add("");
Project project = new Project();
project.addWarnings(warnings);
project.addWarning("WER");
warnings = project.getWarnings();
assertEquals(3, warnings.size());
assertEquals("aso", warnings.get(1));
project.addWarnings(warnings);
warnings = project.getWarnings();
assertEquals(6, warnings.size());
assertEquals("aso", warnings.get(1));
}
@Test(expected = InvalidArgumentException.class)
public void testAddCreationWarnings2() {
List<String> warnings = new ArrayList<>();
warnings.add("xqw\nwer\nt");
Project md = new Project();
md.addWarnings(warnings);
}
@Test
public void testAddCreationWarnings3() {
List<String> warnings = new ArrayList<>();
Project md = new Project();
md.addWarnings(warnings);
assertEquals(0, md.getWarnings().size());
}
@Test
public void testAddLoggingInfo() {
Project project = new Project();
MinervaLoggerAppender appender = MinervaLoggerAppender.createAppender();
logger.warn("test");
logger.warn("test2");
MinervaLoggerAppender.unregisterLogEventStorage(appender);
project.addLoggingInfo(appender);
assertEquals(2, project.getWarnings().size());
}
}
CREATE SEQUENCE project_log_entry_sequence
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
CREATE TABLE project_log_entry_table
(
id integer NOT NULL DEFAULT nextval('project_log_entry_sequence'::regclass),
severity varchar NOT NULL,
type varchar NOT NULL,
object_identifier varchar,
object_class varchar,
map_name varchar,
project_id integer not null,
content text,
CONSTRAINT project_log_entry_pk PRIMARY KEY (id),
CONSTRAINT project_log_entry_project_fk FOREIGN KEY (project_id)
REFERENCES project_table (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
insert into project_log_entry_table (content, project_id, severity, type) SELECT s.token, id, 'WARNING', 'OTHER' from project_table t, unnest(string_to_array(t.warnings, E'\n')) s(token);
insert into project_log_entry_table (content, project_id, severity, type) SELECT s.token, id, 'ERROR', 'OTHER' from project_table t, unnest(string_to_array(t.errors, E'\n')) s(token);
alter table project_table drop column warnings;
alter table project_table drop column errors;
......@@ -8,6 +8,7 @@ import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.ProjectLogEntry;
import lcsb.mapviewer.model.map.OverviewImage;
import lcsb.mapviewer.model.map.OverviewModelLink;
import lcsb.mapviewer.model.map.layout.*;
......@@ -201,17 +202,20 @@ public class ProjectDaoTest extends PersistTestFunctions {
@Test
public void testCreationWarnings() throws Exception {
Project project = new Project("test_project_id");
project.addWarning("warning A");
project.addWarning("warning B");
ProjectLogEntry entry = new ProjectLogEntry();
entry.setContent("content");
entry.setSeverity("WARN");
entry.setType("OTHER");
project.addLogEntry(entry);
project.setOwner(userDao.getUserByLogin(ADMIN_BUILT_IN_LOGIN));
assertEquals(2, project.getWarnings().size());
assertEquals(1, project.getLogEntries().size());
projectDao.add(project);
projectDao.evict(project);
Project project2 = projectDao.getById(project.getId());
assertEquals(2, project2.getWarnings().size());
assertEquals(1, project2.getLogEntries().size());
projectDao.delete(project2);
}
......
......@@ -102,8 +102,7 @@ public class ProjectRestImpl extends BaseRestImpl {
result.put("directory", project.getDirectory());
result.put("progress", project.getProgress());
result.put("notifyEmail", project.getNotifyEmail());
result.put("warnings", project.getWarnings().size() > 0);
result.put("errors", project.getErrors() != null && !project.getErrors().isEmpty());
result.put("logEntries", project.getLogEntries().size() > 0);
result.put("name", project.getName());
result.put("owner", project.getOwner().getLogin());
result.put("projectId", project.getProjectId());
......@@ -579,29 +578,30 @@ public class ProjectRestImpl extends BaseRestImpl {
}
private List<LogEntry> getEntries(Project project, String level) {
List<LogEntry> result = new ArrayList<>();
int id = 0;
for (String s : project.getWarnings()) {
if (!s.isEmpty()) {
if (level.equalsIgnoreCase("warning") || level.equals("")) {
result.add(new LogEntry(id, s, "WARNING"));
}
id++;
}
}
String errors = project.getErrors();
if (errors == null) {
errors = "";
}
for (String s : errors.split("\n")) {
if (!s.isEmpty()) {
if (level.equalsIgnoreCase("error") || level.equals("")) {
result.add(new LogEntry(id, s, "ERROR"));
}
id++;
}
}
return result;
throw new NotImplementedException();
// List<LogEntry> result = new ArrayList<>();
// int id = 0;
// for (String s : project.getWarnings()) {
// if (!s.isEmpty()) {
// if (level.equalsIgnoreCase("warning") || level.equals("")) {
// result.add(new LogEntry(id, s, "WARNING"));
// }
// id++;
// }
// }
// String errors = project.getErrors();
// if (errors == null) {
// errors = "";
// }
// for (String s : errors.split("\n")) {
// if (!s.isEmpty()) {
// if (level.equalsIgnoreCase("error") || level.equals("")) {
// result.add(new LogEntry(id, s, "ERROR"));
// }
// id++;
// }
// }
// return result;
}
private Comparator<LogEntry> getComparatorForColumn(LogSortColumn sortColumnEnum, String sortOrder)
......
......@@ -20,6 +20,7 @@ import com.google.gson.Gson;
import lcsb.mapviewer.api.*;
import lcsb.mapviewer.converter.zip.*;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.ProjectLogEntry;
import lcsb.mapviewer.model.map.MiriamType;
import lcsb.mapviewer.model.map.model.Model;
import lcsb.mapviewer.persist.dao.ProjectDao;
......@@ -211,7 +212,7 @@ public class ProjectRestImplTest extends RestTestFunctions {
project.addModel(model);
project.setOwner(userDao.getUserByLogin(ADMIN_BUILT_IN_LOGIN));
project.setProjectId(model.getName());
project.addWarning("some warning");
project.addLogEntry(new ProjectLogEntry());
}
IModelService mockModelService = Mockito.mock(IModelService.class);
Mockito.when(mockModelService.getLastModelByProjectId(anyString())).thenReturn(model);
......
......@@ -22,14 +22,14 @@ import lcsb.mapviewer.annotation.services.annotators.ElementAnnotator;
import lcsb.mapviewer.commands.*;
import lcsb.mapviewer.common.*;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.common.exception.NotImplementedException;
import lcsb.mapviewer.converter.*;
import lcsb.mapviewer.converter.graphics.DrawingException;
import lcsb.mapviewer.converter.graphics.MapGenerator;
import lcsb.mapviewer.converter.graphics.MapGenerator.MapGeneratorParams;
import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
import lcsb.mapviewer.converter.zip.ZipEntryFile;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.ProjectStatus;
import lcsb.mapviewer.model.*;
import lcsb.mapviewer.model.cache.UploadedFileEntry;
import lcsb.mapviewer.model.map.*;
import lcsb.mapviewer.model.map.layout.*;
......@@ -378,7 +378,7 @@ public class ProjectService implements IProjectService {
analyzeAnnotations(originalModel, params);
}
MinervaLoggerAppender.unregisterLogEventStorage(appender);
project.addLoggingInfo(appender);
project.addLogEntries(createLogEntries(appender));
if (params.isCacheModel()) {
cacheData(originalModel, params);
......@@ -406,7 +406,11 @@ public class ProjectService implements IProjectService {
outOfMemoryBuffer = null;
logger.error("Out of memory", oome);
if (project != null) {
project.setErrors("Out of memory: " + oome.getMessage());
ProjectLogEntry entry = new ProjectLogEntry();
entry.setType("OUT_OF_MEMORY");
entry.setSeverity("ERROR");
entry.setContent("Out of memory: " + oome.getMessage());
project.addLogEntry(entry);
}
updateProjectStatus(project, ProjectStatus.FAIL, IProgressUpdater.MAX_PROGRESS, params);
} finally {
......@@ -602,9 +606,15 @@ public class ProjectService implements IProjectService {
// we need to get the project from db, because session where
// originalProject was retrieved is broken
Project project = getProjectByProjectId(originalProject.getProjectId());
String errorMessage = "Severe problem with removing object. Underlaying eror:\n" + exception.getMessage()
+ "\nMore information can be found in log file.";
project.setErrors(errorMessage + "\n" + project.getErrors());
ProjectLogEntry entry = new ProjectLogEntry();
entry.setType("OTHER");
entry.setSeverity("ERROR");
entry.setContent("Severe problem with removing object. Underlaying eror:\n" + exception.getMessage()
+ "\nMore information can be found in log file.");
project.addLogEntry(entry);
project.setStatus(ProjectStatus.FAIL);
projectDao.update(project);
} finally {
......@@ -1061,10 +1071,15 @@ public class ProjectService implements IProjectService {
try {
Project project = getProjectByProjectId(params.getProjectId());
String errorMessage = "Problem with uploading to database. "
ProjectLogEntry entry = new ProjectLogEntry();
entry.setType("DATABASE_PROBLEM");
entry.setSeverity("ERROR");
entry.setContent("Problem with uploading to database. "
+ "You might violated some unhandled constraints or you run out of memory. Underlaying eror:\n"
+ e.getMessage() + "\nMore information can be found in log file.";
project.setErrors(errorMessage);
+ e.getMessage() + "\nMore information can be found in log file.");
project.addLogEntry(entry);
project.setStatus(ProjectStatus.FAIL);
projectDao.update(project);
} catch (Exception e) {
......@@ -1091,7 +1106,11 @@ public class ProjectService implements IProjectService {
logger.error("Problem with uploading project " + params.getProjectId(), e);
Project p = projectDao.getProjectByProjectId(params.getProjectId());
if (p != null) {
p.setErrors("Problem with uploading map: " + e.getMessage() + ". More details can be found in log file.");
ProjectLogEntry entry = new ProjectLogEntry();
entry.setType("OTHER");
entry.setSeverity("ERROR");
entry.setContent("Problem with uploading map: " + e.getMessage() + ". More details can be found in log file.");
p.addLogEntry(entry);
}
updateProjectStatus(p, ProjectStatus.FAIL, IProgressUpdater.MAX_PROGRESS, params);
......@@ -1148,4 +1167,8 @@ public class ProjectService implements IProjectService {
return project;
}
private Set<ProjectLogEntry> createLogEntries(MinervaLoggerAppender appender) {
throw new NotImplementedException();
}
}
......@@ -14,8 +14,7 @@ import org.springframework.stereotype.Component;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.common.IProgressUpdater;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.ProjectStatus;
import lcsb.mapviewer.model.*;
import lcsb.mapviewer.model.map.layout.ReferenceGenome;
import lcsb.mapviewer.model.user.ConfigurationElementType;
import lcsb.mapviewer.services.interfaces.*;
......@@ -136,18 +135,15 @@ public class StartupBean {
try {
for (Project project : projectService.getAllProjects()) {
if (!ProjectStatus.DONE.equals(project.getStatus()) && !ProjectStatus.FAIL.equals(project.getStatus())) {
String errors = project.getErrors();
if (errors == null || errors.trim().isEmpty()) {
errors = "";
} else {