I'm working on a web app that will be used for writing reports. It's for a friend who will do service tests on businesses for his clients who are importers (testing how they perform in client service and other services). So the app is fairly straight forward, allowing for the writing of reports and downloading them in pdf. The report has parts which will cover different aspects of the services provided by the businesses. Each part will have question groups covering more specific aspects of the services. These groups have a list of questions that can be of different type: multiple choice, questions with answers in plain text, etc. The reports will be stored in a database using JPA 2.0 (EclipseLink). There will be report templates for each client, with the report parts, question groups and questions for businesses to be tested for the particular client.
I have only very limited experience in coding and Java so I'd like to have some guidance with regard to certain aspects of the app. I do have it written to a point were its working and just needs certain fixes. I'm not sure the class structure is correct though. And even though it's working and I'm sure it would do its job just fine, I'd like to know how to do it properly.
The class structure is as follows. The Report class has as its property an ArrayList of ReportParts. ReportPart has as its property an ArrayList of QuestionGroups. QuestionGroup has as its property an ArrayList of Questions. Question has subclasses for the various types of questions, for example MultipleChoiceQuestion. Answers to the questions are instances of Answer class, which also has subclasses based on the type of question and answer.
And here's the issue: for now, answer is a property of Question. Is this cool or what would be the correct way of doing this? Does this have implications for JPA 2? For now, I haven't written a tool for preparing report templates for each client. Instead, the templates are hard coded for now. There won't be many templates and they will only be modified occationnally, maybe once a year, so from that perspective hard coding for now shouldn't be a problem. So now the entire report is saved in the database as new instances, question groups, questions and all, together with the answers. But if i code a tool for doing the templates the questions will no longer be saved as separate instances, so shouln't the instances of Answer refer to the particular instance of Report instead of Question?
More generally, I'm wondering what the proper practice would be. I though of using a Map with Question-Answer pairs. However, the JSP for filling in the report uses Spring form binding and I'm not sure it can work with Maps. There are several nested loops for looping through the parts and questions. As far as I understand, Spring input tags' path-attribute needs to go all the way from ModelAttribute (instance of Report) to the property the user input is to be bound to. So for now i use indexes to navigate through the iterated ArrayLists to the property the input is to be bound to. I think this is not possible with Maps and you can't use indexes with Maps?
The Question class also has as its property an ArrayList of SubQuestions. SubQuestion has as its property a Question. The reports need to have questions that are linked to the previous question that, for example, go into further detail on the answer provided to the previous question. These questions can also be of any of the type mentioned above. The reason for this class is that these questions should be shown in the report indented under the primary question. The different subclasses of Question can't inherit from both Question and SubQuestion so I ended up with this solution. The whole thing doesn't look too nice structurally but I don't know if this is wrong?
So my question is, how does this structure look and should it be done differently?
My second question. I'm really a noob with JPA 2 and don't have much experience working with databases in general. So I would like to ask, how should the report templates be stored? What would be the best way of saving these templates (the lists of report parts, question groups and questions for a report for a particular client)? As said, for now the templates are hard coded but I would like to change that once the app is otherwise done.
Bonus question: As said, the report should be made available in pdf. For now, with great pain, I have rigged a JSP to work so that it can be printed to pdf and layout and pagination works decently. Converting the report to pdf on a browser is sufficient for now, as my friend is just getting started with his business and he basically needs to do a report every now and then. He can email the pdfs to his clients. Clients should have access to the app early next year though and at that point they should be able to download their reports from the app directly. So my question is: what's your recommended way for doing reports like this in pdf? I will be looking into JasperReports. How does it handle this kind of reports with nested loops for report parts, question groups and questions and where the answers need to be presented differently based on the type of question (text, multiple choice, etc.)?
Sorry for the wall of text and thanks for making it this far! Any guidance will be greatly appreciated!
Let talk design. Forget the tools or technologies for a minute.
Requirement: Your so-called report will list a series of questions and their corresponding answers for different clients in PDF format.
First you need to start from the database or the data. How to store/present such data the simplest? Then how to display such data (data structure to use).
I would use a map to store such data (eg Map<Question, List<Answer>>) = a question can have many answers.
Database structure, to keep it simple 2 tables: 1) Question, and 2) Answer. The Answer table needs to know what Question it belongs to.
qid bigint (foreign key to Question)
anstype varchar (MC or free text or whatever)
answer varchar (the actual answer)
Given this Map<Question, List<Answer>>, looping it to display the content will look like:
Suppose that is how you get the data, then we can talk about the tool for creating reports.
Given your current approach is hard-coding in java/jsp which can become error-prone/tedious. In fact if the report content is dynamic (eg from the DB), then the template can be one size fits all (assuming all clients display the same layout/stuff).
What tool to use? I recommend Jasper Reports. You can build the report template with the client software then use java code to generate the report.
Suppose you follow through, on the web front, calling the java code will be the same allowing the report generation code to be reused . FYI it shouldn't matter if the web front is Spring or pure JSP or JSF or whatever framework.
Thanks a lot for the very helpful answer! I feel a bit silly now It seems obvious now, I don't know how I got on the wrong track. I guess it's because I started by doing the report structure and doing JSP:s for it and it seemed like the answers need to go in there somewhere and just stuck them in. Silly me. And I'll have a look at JasperReports once I fix my class structure. It seems everyone is saying good things about it. I'll have to see how much work it will be to do a report template that loops through report parts and questions and such and that displays the various kinds of questions and answers. I'm interested to learn to use it.
So i think the way i will go is remove from Report all thats related to Answer, rename the class ReportTemplate and create a new Report class with the properties ReportTemplate template and Map<Question, Answer> answers. Answer also needs to have as its property the Question it refers to. Seems simple now... Should be a minor change in code. JSPs are dynamic with loops, not hard coded which would have been too much. They should actually become more simple since the spring input tag path attributes will be shorter. I think ReportTemplate needs to have boolean property "current" so the current template to use for a particular client is identified, unless there is some other way of doing this with jpa 2?
Edit: oh and, yes using jasperreports for web presentation would be handy but i already have my pretty, dynamic showReport.jsp with amazing jquery panels and twitter bootstrap css thats just too amazing :-D. So pdf is just for the printout/download
Don't know spring that well so I can't comment on your integration.
Regarding JasperReport template, it's basically sql or view or store procedure. If the sql output is correct, your java code will able to use it to populate the Map<Question,List<Answer>> structure. (It's not the other way around).
Depending on how your report is laid out, you may need sub-report. Anyway try to keep it simple for now.