Can I make a constructor for a custom annotation? - java

I am trying to make an annotation for different methods and classes to programmatically keep track of all the rules, so I can display them to the user.
I would like the annotation class Rule to record all the places that the annotation is used. As a first step, I tried adding a single static counter to the class, here's what the Rule annotation looks like:
public #interface Rule {
static int count = 0;
String name();
String description(); //Note the parentheses
public Rule(String name, String description) {
count++;
this.name = name;
this.description = description;
}
}
The way I would use it is like this:
public class Airline {
private String code;
#Rule(name = "Formatted Code", description = "e.g. Format 'la' as 'LA'")
public String codeFormatted() {
return code.toUpperCase();
}
public static void main(String args[]) {
System.out.println(Rule.count);
}
}
Without the Rule public constructor, this compiles using javac version 1.8.0_162.
When I add the public constructor (to increment Rule.count), I get compiler errors:
javac Rule.java
Rule.java:6: error: <identifier> expected
public Rule(String name, String description) {
^
1 error
Compilation exited abnormally with code 1 at Thu Mar 22 19:58:39
What am I missing in my Rule constructor?
Or, is this a completely ridiculous idea and I should feel bad? I can't tell, still getting used to annotations.

Related

Check getter value by list of property name

First of all, sorry if my question seems basic. I suppose I have one class with 100 properties and 100 getters and setters.
I'm aiming check not null value of some of these properties.
Exemple :
If (object.getPropertyName()==null) System.out.println(" null value of Property Name")
I wana do this for 50 properties. I could provide a list of properties to be checked in input. Is there anyway to capture getter name by property name and check them one by one without writing this 50 times ?
Thanks
Yes sure, you can use this library here: de.cronn.reflection-util.
It allows you to obtain descriptors from specific field names and then call their respective get/set methods. Like in the following source code:
public class Test {
public static void main(String[] args) {
Example example = new Example();
example.setName("Test");
PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptorByName(example, "name");
System.out.println((String) PropertyUtils.read(example, descriptor)); // Will call getName
}
}
public class Example {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

No applicable constructor/method found for actual parameters "int" but the matching candidate does exist

I want to add some code inside the Spark-SQL generated java code. So I create a jar file that has a class "Employee" and manually insert 'Employee e = new Employee(some integer)' in the file: sql/core/src/main/scala/org/apache/spark/sql/execution/WholeStageCodegenExec.scala.
When invoking spark-shell, I did 'spark-shell --jars /path/to/myJar.jar'. However, when I run the query, it reports this error:
ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 21, Column 18: No applicable constructor/method found for actual parameters "int"; candidates are: "Employee()", "Employee(int)", "Employee(java.lang.String)"
Most similar questions I found online are because the parameter type mismatch, however, I do have Employee(int) constructor as you can see here, why Janino still complained about it??
My Employee example is pretty simple:
public class Employee {
String name = "Default";
int age;
int ID;
Employee() {
System.out.println("Empty constructor");
}
Employee(String myName) {
name = myName;
}
Employee(int myAge) {
age = myAge;
}
void sayHi() {
System.out.println("Hello, I'm " + name);
}
void sayhello() {
System.out.println("Hello,test");
}
}
And the modified generated code is also simple as:
public void init(int index, scala.collection.Iterator[] inputs) {
String name = "Go";
int age = 30;
Employee e1 = new Employee(age);
e1.sayHi();
Really appreciate your help!!!
I'm not familiar with the Spark codegen, but it's one issue with the Java code.
All constructors of the Employee class are decrared with the default access, so they are not accessible from the other packages. Try to declare constructor with public modifier.

AssertJ: Testing exceptions with messages generated with String.format

I'm wondering if there is a clean and complete way to assert on the message attached to a thrown exception when that message was generated using String.format(). For example, a class like:
public class Car {
public static final String DRIVE_ERROR = "Can't drive while car %s is parked!";
private String name;
private boolean parked;
public Car(String name) {
this.name = name;
this.parked = true;
}
public void drive() {
if (parked) {
throw new IllegalStateException(String.format(DRIVE_ERROR, name));
}
}
}
(Sorry for the weird example, just trying to keep it as simple as possible)
Now if I were testing the car, I'd have a class like this:
public class CarTest {
#Test
public void drive_test() {
Car car = new Car("Greased Lightning");
assertThatThrownBy(() -> car.drive())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("???");
}
}
The question is, what is the best way to assert on the message? In this example, I could separate out the declaration of the name of the car, then use String format myself to grab the static string from Car and format in the name, but that seems like a lot of extra code, and can't be easily used in a lot of instances (eg. when the item that goes in the formatted string is determined at runtime). What I'd really like to be able to do is pass the error message string to hasMessageContaining and have it ignore the "%s" placeholder and accept anything in that spot. Is there a way to do regex matching of Strings with assertJ? Or some other way of doing this cleanly?
EDIT: I'm also open to alternatives on throwing exceptions that have messages that are easier to test. One solution is just using String concatenation, like throw new Exception(STATIC_ERROR_MESSAGE + name) and then testing that the message contains the first part, but that really limits your message formatting ability and doesn't look very clean.
Exception message assertions are limited compared to regular String assertion.
What you could do is use matches or containsPattern assertions, ex:
#Test
public void test() {
// GIVEN some preconditions
// WHEN
Throwable thrown = catchThrowableOfType(() -> { throw new IllegalStateException("boom!"); },
IllegalStateException.class);
// THEN
assertThat(thrown.getMessage()).matches(".oo.")
.containsPattern("oo.");
// or even better thanks to Rolland Illig suggestion
assertThat(thrown).hasMessageMatching(".oo.");
}
Note that by using catchThrowableOfType you don't have to check that the caught exception is of the expected type anymore.

Is it possible to build an object like this at runtime in java?

As the title says....
I want to build a POJO with four field variables and at certain runtime events create an instance of this POJO with access to possibly maybe two or three of the fields.
public class Category implements Serializable {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Lets say I create a new Category object but I only want to be able to have access to the name field during runtime. Is there a design pattern I can use to achieve this? I thought about the strategy pattern and looked at the builder but I am still confused if I can do this in java.
Basically the overall goal is to grab an object from a database and return it as a JSON response in jax rs. But sometimes I dont want a complete object returned but only lets say halve of the object to be accessible at during certain runtime events. My apologies if this seems like a dumb question but I know what I want to do but just don't know the best way.
I have the same problem with you, and my project was used springmvc,and the json tool is jackson.With the problem solved, I just use #JsonIgnore.For more details,just read jackson-how-to-prevent-field-serialization
So someone correct me if I am wrong or see a better option than this...with alot of objects this can be alot of extra code for serialization and deserialization...Jackson Provisions is what I need. I can use the annotation #JsonView(DummyClass.class) on the field variable. I will accept this a the best answer in a day or two unless someone else posts a better response.
// View definitions:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
public class Bean {
// Name is public
#JsonView(Views.Public.class) String name;
// Address semi-public
#JsonView(Views.ExtendPublic.class) Address address;
// SSN only for internal usage
#JsonView(Views.Internal.class) SocialSecNumber ssn;
}
With such view definitions, serialization would be done like so:
// short-cut:
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
// or fully exploded:
objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
// (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
objectMapper.writeValue(out, beanInstance); // will use active view set via Config
// or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
This information was pulled from http://wiki.fasterxml.com/JacksonJsonViews
with jackson 2.3, I can do this with JAX-RS
public class Resource {
#JsonView(Views.Public.class)
#GET
#Produces(MediaType.APPLICATION_JSON )
public List<Object> getElements() {
...
return someResultList;
}
}

using eclipse template to create test cases

Often do I find myself creating the same unit tests methods to getters\setters, c'tors and Object methods (hashCode, equals and toString).
What I'm trying to achieve, with the help of Eclipse IDE, is automation of this procedure.
consider this example:
public Class Person {
private String id;
private String name;
public Person(String id, String name){
this.id = id;
this.name = name;
}
public String getId() { return id; }
public void setId(String id) {
this.id = id;
}
public String getName() { return name; }
public void setName(String name) {
this.name = name;
}
#override
public int hashCode(){ ... }
public boolean equals(Person other){ ... }
public String toString(){ ... }
/* this class may implement other logic which is irrelevant for the sake of question */
}
The unit test class will look something like this:
public class PersonTest extends TestCase
{
#override
public void setup() {
Person p1 = new Person("1","Dave");
Person p2 = new Person("2","David");
}
#override
public void tearDown() {
Person p1 = null;
Person p2 = null;
}
public void testGetId() {
p1.setId("11");
assertEquals("Incorrect ID: ", "11", p1.getId());
}
public void testGetName() { /* same as above */ }
public void testEquals_NotEquals() { /* verify that differently initialized instances are not equals */ }
public void testEquals_Equals() { /* verify that an object is equals to itself*/ }
public void testHashCode_Valid() { /* verify that an object has the same hashcode as a similar object*/ }
public void testHashCode_NotValid() { /* verify that different objects has different hashcodes*/ }
public void testToString() { /* verify that all properties exist in the output*/ }
}
This skeleton is similar to the vast majority of classes created.
can it be automated with Eclipse?
Have a look at Fast Code. It is an eclipse plugin that provides very nice feature of templating stuff which is what you seem to be looking for. On the documentation page look for Create Unit Test section.
A very useful feature of this plugin is to create unit tests automatically. Unit tests can be of type Junit 3, Junit 4 or TestNG. For Junit 4 or TestNG tests, appropriate annotations will be automatically added. One needs to configure it just once.
Unit tests are meant to show that an Object's behaviour is conforming to it's expected behaviour. They are not meant to make sure that the Java language is working correctly.
What you have here is a fancy data structure, with no behaviour. In that case every assignment is mediated by a method call, and every dereference is also mediated by a method call. Since Object Oriented programming is "data + behaviour" = objects, and this code lacks behaviour, it's a candidate for being called non-object-oriented code.
Sometimes Java uses non-object-oriented classes to facilitate transfer of information. The class guarantees that all information gets transferred as one unit when doing serialization. So having such a class isn't an indicator that the code is wrong; however, if you run into too many classes like this then something is very wrong.
One key element of testing is that it's not really a test if the test cannot fail. If the test cannot fail, it's just busywork. Assuming that one of these fields cannot be null then the setter might look like
public void setName(String name) {
if (name == null) throw new IllegalArgumentException("name cannot be null");
this.name = name;
}
And then you have something to test. Otherwise, your just checking to see if the assignment operator failed. As an aside, if the assignment operator failed, then I'd wager that the JVM is going to come down pretty hard sooner (rather than later) and you can't trust your tests to report correctly either.

Categories