I have build an application for dynamic compile java source code and fetch the compiled class information and stored to object.
The application required source directory and full qualify class name (ex. MOCG.entity.Person) for adding file to the application.
I use the Janino compiler in this application. I used to implement by javax.tools.ToolProvider compiler but I dont know how to compile multiple file, and it cannot automatically compile related class.
For now my code work just fine but when I try to compile an interface class or abstract class it always return error :
Caused by: org.codehaus.commons.compiler.CompileException: File /Users/chillyprig/IdeaProjects/Mockito/src/lab05/p1/dao/CourseDAO.java, Line 22, Column 9: Identifier expected in member declaration
at org.codehaus.janino.Parser.throwCompileException(Parser.java:2593)
at org.codehaus.janino.Parser.parseInterfaceBody(Parser.java:613)
at org.codehaus.janino.Parser.parseInterfaceDeclarationRest(Parser.java:518)
at org.codehaus.janino.Parser.parsePackageMemberTypeDeclaration(Parser.java:186)
at org.codehaus.janino.Parser.parseCompilationUnit(Parser.java:74)
at org.codehaus.janino.JavaSourceIClassLoader.findIClass(JavaSourceIClassLoader.java:150)
... 46 more
This is an input file :
/**
* Created with IntelliJ IDEA.
* User: Dto
* Date: 12/2/12
* Time: 8:26 AM
* To change this template use File | Settings | File Templates.
*/
package lab05.p1.dao;
import java.util.List;
import java.util.Set;
/**
* This is the example of the DAO interface, you have to implement the implementation class to complete the DAO classes
* #author dto
*/
public interface CourseDAO {
/**
* Get all the courses
* #return all courses stored in the persistence
*/
List<Course> getCourses();
/**
* Get all students which enroll to the courses
* #return all students in the persistence
*/
Set<Student> getStudents();
/**
* Get the course by query the name provided
* #param name the name of the course which the user wants
* #return the course which contains the same name
* null if the course with specific name is not existed
*/
Course getCourseByName(String name);
/**
* Get the Student by id
* #param id the id of the student which we want to find
* #return the student object with the specific id
* The empty student object if the student with the specific id is not exist
*/
Student getStudentById(String id);
}
This is my snipped code for compilation :
private Class compile() throws ClassNotFoundException, SourceDirectoryNotfoundException {
ClassLoader classLoader = null;
try{
classLoader = new JavaSourceClassLoader(
Thread.currentThread().getContextClassLoader(),
new File[] {new File(sourceDir)},
(String) null
);
} catch (NullPointerException e){
throw new SourceDirectoryNotfoundException();
}
Class<?> c = classLoader.loadClass(fullname);
return c;
}
Every suggestion is very appreciate. Any code example would be nice.
Janino is a Java 1.4 compatible compiler -- i.e., it can't handle generics, which were introduced in Java 5. Line 22 is the line that begins List<Course> -- a use of generics, which this compiler can't handle.
Related
So I have been looking around and reading up a lot of forums and the java documentation but I can't seem to get a solid solution for what I am trying to do.
Essentially I have a Module class as shown below:
/**
* MODULE CLASS
* This class will be the base for every Module inputed into the system
* #author George
*/
public class Module {
// -=VARIABLE DECLARATIONS=-
private String moduleName; /* String variable to store the name of the module */
private String moduleLeader; /* String variable to store the name of the module leader */
// -=GETTERS=-
public String getModuleName() {return this.moduleName;} /* Will return the name of the module */
public String getModuleLeader() {return this.moduleLeader;} /* Will return the name of the module leader */
// -=SETTERS=-
public void setModuleLeader(String l) {this.moduleLeader = l;} /* Sets the name of the module leader to the inputed name */
public void setModuleName(String n) {this.moduleName = n;} //THIS NEEDS TO BE ADDED TO DESIGN DIAGRAMS
// -=CONSTRUCTOR=-
/**
* Constructor to make a new object for the module
* #param n (NAME) - String input to set the name of the module
* #param l (LEADER) - String input to set the name of the module leader
*/
public Module(String n, String l) {
this.moduleName = n;
this.moduleLeader = l;
}
}
On my GUI, each module is represented as its own button which upon clicking will take you to the module's page using CardLayout. I also have a button where the user can add a module, this is where my issue comes into place. Obviously a Module object would be defined as:
Module newModule = new Module("name", "leader");
But how would this allow more than one object to be created. The name of the module would come from user input so there is no way I can put the name of the object in the source code and from what I have read you cannot set the object name using a variable.
Lets say for example, during runtime, the user would want to create two modules. One with the name of "Java" and one with the name of "Python". How would I go about doing this? Obviously the first object would be created just fine using the initialization above, but the name of the object would be stuck as newModule. But then it would not be able to create the second object as it cannot have two objects with the same name. I have spent some time trying to understand HashMaps to see if that could be of any use to me but quite frankly I find it quite confusing and again, I can't tell if that is the correct solution.
I hope I have worded this correctly and you can understand my problem. Any help with this would be greatly appreciated.
Thanks in advance.
This is a small Java application that is designed to calculate a departments total monthly expenses by adding the amounts paid to all the employees in that department. The departments employees are arranged in a hierarchy, which this app seeks to take into account with how it arranges objects.
I'm new to JUnit and unit testing. I'm attempting to run a test comparing my actual total to an expected total. However, I'm getting a number of error(detailed in the source code below).
Note I'm using: Windows 8.1, Java SE 8, eclipse Luna, JUnit 4.
I have 1 main question, & 1 side questions:
Could you help me to understand what is causing these errors and what I can do to correct them?
I'm trying to improve my documentation style by moving from 'comments' to something a little more professional. Could this documentation be improved?
Thanks for taking a look.
Unit Test
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import expenseApp.Developer; // The import expenseApp cannot be resolved
import expenseApp.Manager; // The import expenseApp cannot be resolved
import expenseApp.QATester; // The import expenseApp cannot be resolved
/**
* TestClass evaluates a departments actual total expenses,
* by comparing them to a projected total.
* #author Reed
*/
public class TestClass {
/**
* testOne() compares a departments actual total expenses with a projected total of $2100.00.
* This departments employees create the following hierarchy:
* managerA <-- managerB <-- tester1 & dev1.
*/
#Test
public void testOne()
{
QATester tester1 = new QATester(); // Multiple markers at this line - QATester cannot be resolved to a type x2
Developer dev1 = new Developer(); // Multiple markers at this line - Developer cannot be resolved to a type x2
Manager managerB = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerB.add(tester1);
managerB.add(dev1);
Manager managerA = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerA.add(managerB);
assertEquals(managerA.getTotalExpenses(), 2100.00, 0.00);
fail("Not yet implemented"); // automatically generated, should I use this?
}
}
App
//Employee
package expenseApp;
/**
* Employee is the abstract superclass of Manager, QATester, and Developer.
* Employee declares public abstract double getExpenses().
* #author Reed
*/
public abstract class Employee
{
/**
* getExpenses() returns the monthly allocation amount of a Manager, Developer, or QATester object.
* #return a double values representing what the specified Employee is paid each month.
*/
public abstract double getExpenses();
}
// QATester
package expenseApp;
/**
* QA Testers warrant a monthly allocation of $500.00, per QA Tester.
* QATester extends Employee.
* #author Reed
*/
public class QATester extends Employee
{
/**
* getExpenses() returns a QA Testers monthly allocation amount.
* #return a double value of 500.00.
*/
#Override
public double getExpenses()
{
return 500.00;
}
}
// Developer
package expenseApp;
/**
* Developers warrant a monthly allocation of $1000.00, per Developer.
* Developer extends Employee.
* #author Reed
*/
public class Developer extends Employee
{
/**
* getExpenses() returns a Developers monthly allocation amount.
* #return a double value of 1000.00.
*/
#Override
public double getExpenses()
{
return 1000.00;
}
}
// Manager
package expenseApp;
import java.util.ArrayList;
/**
* Managers warrant a monthly allocation of $300.00, per Manager.
*
* A manager is at the top of a hierarchical relationship,
* in which one manager oversees employees such as developers,
* QA testers, & other managers. An employee's title is associated with
* an amount that type of employee is paid monthly.
* A compete hierarchy constitutes all the employees of a department.
* A departments expenses can be determined by adding the amounts
* paid to the employees in a hierarchy.
*
* Manager extends Employee.
*
* #author Reed
*/
public class Manager extends Employee
{
private ArrayList<Manager> managerList = new ArrayList<>();
private ArrayList<Employee> employeeList = new ArrayList<>();
/**
* Add() adds employees to a list.
* If the employee is a manager, managerList.
* Else, the employee is a developer or QA tester, employeeList.
* #param employee
*/
public void add(Employee employee)
{
if(employee instanceof Manager)
{
managerList.add((Manager) employee);
}
else
{
employeeList.add(employee);
}
}
/**
* getExpenses() returns a Mangers monthly allocation amount.
* #return a double value of 300.00.
*/
#Override
public double getExpenses()
{
return 300.00;
}
/**
* getTotalExpenses() adds the values in managerList and employeeList,
* calculating a departments total monthly expenses.
* #return the value of totalExpenses.
*/
public double getTotalExpenses()
{
double totalExpenses = 0.00;
for(Manager manager : managerList)
{
totalExpenses += manager.getTotalExpenses();
}
for(Employee employee : employeeList)
{
totalExpenses += employee.getExpenses();
}
return totalExpenses;
}
}
import expenseApp.Developer; // The import expenseApp cannot be resolved
This error means that Eclipse can't find the code for the class Developer. This problem is not related to JUnit or unit tests.
Make sure your build path contains the necessary JARs and projects.
Also, remove the fail() at the end of the test since you have now implemented the test.
documentation
A better way to document is to use variables:
double expected = 2100.0;
double maxDelta = 1e-6;
assertEquals(expected, managerA.getTotalExpenses(), maxDelta);
The variables explain what a value means. "2100" means nothing. "expected" communicates: That's the expected result.
You could use expectedDollars to say "this value is in dollars".
If you have only short pieces of code, don't document them. People can read the code to understand what is going on. But you can help them by adding methods with useful names:
Manager managerB = managerWithADevAndTester();
Manager managerA = createManagerFor( managerB );
or, if you prefer simple DSLs:
Manager managerB = createManagerFor(
new QATester(),
new Developer()
);
Manager managerA = createManagerFor( managerB );
Based on our comment discussion, it seems you wrote your unit tests in another Eclipse project. Typically tests are located within the same project, thus they benefit from having all the project classes on the classpath.
If you'd like to use a separate project, you'll need to edit the test project properties to tell Eclipse that you have a dependency on your main project.
The fail call at the end of the test case should be removed, that will always fail the test regardless of the assertion result on the line above.
I'm working with Mybatis 3.2.6 and implementing a custom resulthandler. I've done this before using a simple datatype parameter and have had no problems. This time around I need to pass in several arguments... The signature I'm using is
session.select(statement, parameter, handler);
For parameter I've created a simple POJO to easily send in what I need. It is as follows:
public class DifferenceParam {
private int current;
private int compare;
private String table;
private String comparator;
/**
* Constructor excluding comparator. Will default a value of
* "code" to compare content on, e.g., <br/>
* {#code select * from a minus select * from b where a.code = b.code } <br/>
* #param table
* #param current
* #param compare
*/
public DifferenceParam(String table, int current, int compare) {
this(table, "code", current, compare);
}
/**
* Constructor providing a specific column to compare on, e.g. <br/>
* {#code select * from a minus select * from b where a.[comparator] = b.[comparator] } <br/>
* #param table
* #param comparator
* #param current
* #param compare
*/
public DifferenceParam(String table, String comparator, int current, int compare) {
this.table = table;
this.comparator = comparator;
this.current = current;
this.compare = compare;
}
/** Appropriate setters and getters to follow **/
}
The handler implementation is irrelevant at the moment, because I get an exception well in advance... The query I'm executing is:
<select id="getCodeSetModifications" parameterType="DifferenceParam" resultType="Code">
select *
from
(
select * from ${param.table} where revision_seq = #{param.current}
minus
select * from ${param.table} where revision_seq = #{param.compare}
) a, ${param.table} b
where a.${param.comparator} = b.${param.comparator}
and b.revision_seq = #{param.compare}
</select>
Here is the interface as well
public List<Code> getCodeSetModifications(#Param("param") DifferenceParam param);
The problem I'm having is that execution via a mapper e.g.,
session.getMapper(DifferenceParam.class);
works just fine, but when I invoke through a select on the session I get the following exception.
Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'param' in 'class com.mmm.his.cer.cerval.uidifference.map.param.DifferenceParam'
Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'param' in 'class com.mmm.his.cer.cerval.uidifference.map.param.DifferenceParam'
I've debugged as far as I can go into Mybatis, but am having no luck.
Thanks in advance...
When you use session.getMapper(DifferenceParam.class);, mybatis looks for #Param annotation and uses it's value in query.
When you invoke session.select(statement, parameter, handler);, such mapping doesn't occur.
Try to add public DifferenceParam getParam() { return this; } to DifferenceParam to workaround this.
when the MyBatis query only have one param. Don't need #{param.} reference.
because it default use the only param.
so when u use ${param.table}, it actually using #{DifferenceParam.param.table}.
because it think the ${param.} inside of the #{DifferenceParam.}
I would like to create a template to automatically make my Javadoc documentation when I create a method. For example if I create a method:
protected User createUser_1P(String uname, String[] stocks) throws ElementAlreadyExists {
...
return u;
}
I would like the template to generate something like this:
/*
* #param uname user name
* #param stocks list of stocks
* #return User
* #throws ElementAlreadyExists
*/
Any help will be apreciated. Thanks
To generate JavaDoc for your method in IntelliJ all you need to do is to type /** on the line above the method definition and hit Enter.
For your method the following JavaDoc will be generated:
/**
*
* #param uname
* #param stocks
* #return
* #throws ElementAlreadyExists
*/
protected User createUser_1P(String uname, String[] stocks) throws ElementAlreadyExists {
...
return u;
}
Mind you that IntelliJ does not provide with any descriptions, you will have to fill them out.
I use JAXB for mapping XML configuration to Java object. This configuration could be edited from UI, that's why in order to transfer it to UI and vice versa. I definitely need to unmarshall json into Java object. Hence it's required to have setter method for List.
How to generate setter method for List property for POJO class using JAXB?
For security reasons setter are not generated for List objects.
/**
* Gets the value of the dateIntervals property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the dateIntervals property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getDateIntervals().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link DateInterval }
*
*
*/
For that you need create variable of List.The setter getter methods for this List variable are as below.
package foo.bar.me.too;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="VisitorDataList")
public class visitordatalist {
List<visitordata> vstd;
#XmlElement(name="VisitorData")
public List<visitordata> getVstd() {
return vstd;
}
public void setVstd(List<visitordata> vstd) {
this.vstd = vstd;
}
}