I want to return a list of enums from a rest api call, and have it show the value of the enum rather than just the enum names, in JSON format. Currently my rest call returns json looking like:
{
"responses": [
"ACTION_TAKEN",
"IGNORED",
"UNDETECTED"
]
}
But, I want it to be more like (or something like this):
{
"responses": [
{
"name":"ACTION_TAKEN",
"value":"Action Taken"
},
{
"name":"IGNORED",
"value":"Ignored"
},
{
"name":"UNDETECTED",
"value":"Undetected"
}
]
}
My enum looks like:
public enum Response {
ACTION_TAKEN ("Action Taken"),
IGNORED ("Ignored"),
UNDETECTED("Undetected");
private String value;
Response(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
#Override
public String toString() {
return value;
}
}
My model object looks like this. For the sake of this example, it just has a list of enum values.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class StaticData {
private List<Response> responses;
public List<Response> getResponses() {
return responses;
}
public void setResponses(List<Response> responses) {
this.responses = responses;
}
}
The web service method looks like:
#Component
#Path("staticData")
#Produces("application/json")
#Consumes("application/json")
public class StaticDataResource {
#GET
public Response getCurrentContent() {
StaticData staticData = new StaticData();
staticData.setResponses(Arrays.asList(Response.values()));
return Response.ok(staticData).build();
}
}
Here are the dependencies from my effective pom (sorry for the bad formatting)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.19.1</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.19</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.19</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>javax.ejb-api</artifactId>
<version>3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
I have tried adding #JsonFormat(shape = JsonFormat.Shape.Object) to the top of my enum class. It didn't work. I tried adding #JsonValue to above my getValue() method in the enum class, and that didn't work either. I tried adding a custom serializer extending StdSerializer or JsonSerializer, and referencing that class above my enum using #JsonSerialize(using = ReasonSerializer). I put a breakpoint in the serialize method and didn't hit it, so that didn't work. I looked a little bit at doing implements ContextResolver<ObjectMapper>, but couldn't quite figure that out, or whether that was even the right path to go down or not.
Any help is greatly appreciated! Thanks!
Final solution
This works with JAX-RS and I have tested it with your code.
Use #JsonFormat with public String getName().
#JsonFormat(shape=JsonFormat.Shape.OBJECT)
public enum Response {
ACTION_TAKEN ("Action Taken"),
IGNORED ("Ignored"),
UNDETECTED("Undetected");
private String value;
Response(String value) {
this.value = value;
}
// Getters, Setters
public String getName() {
return name();
}
}
JSON output
{
"responses": [{
"value": "Action Taken",
"name": "ACTION_TAKEN"
}, {
"value": "Ignored",
"name": "IGNORED"
}, {
"value": "Undetected",
"name": "UNDETECTED"
}
]
}
Tested using the following dependency.
import com.fasterxml.jackson.annotation.JsonFormat;
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
Alternative solution
Jackson docs states that behavior may change depending on what serializer is being used. So if the first solution doesn't work, this one might.
#JsonFormat(shape=JsonFormat.Shape.OBJECT)
public enum Response {
ACTION_TAKEN ("Action Taken"),
IGNORED ("Ignored"),
UNDETECTED("Undetected");
private String name;
private String value;
Response(String value) {
name = name();
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}
According to this page:
https://www.javaworld.com/article/2072870/java-enums-are-inherently-serializable.html
Every Enum is naturally serializable, so yours should work too.
But, you should consider what was said here:
Is custom enum Serializable too?
Summary:
"Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form"
To solve your problem I would consider using a simple Pojo class to represent your serializable class. If you still wants to use a Enum, then you could use a translator Pojo <-> Enum (I do not recomend doing this last option because of the redundancy, but last word should be yours depending on what you want to do with it :) ).
Related
I have to convert a XML using gson library into a JSON
i haven´t found how to do it using gson library(java)
You could use Jackson to do this:
import these libraries:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.1</version>
</dependency>
then do this in your class:
public class Example {
private String name;
private int number;
}
Example example = new XmlMapper().readValue(xml, Example.class);
String json = new ObjectMapper().writeValueAsString(example);
I'm having a bizarre situation on a new setup using vanilla Spring Boot 2/Spring 5/Java 10/Jigsaw where no matter what I do, pulling an object through Spring MVC gives me an empty {} JSON object instead of my object properties.
BUT ... if I use an Accept header of application/xml instead of application/json, I get all the right properties. Maybe I'm losing my mind but I seem to recall in previous versions that if it worked on one side (xml), it should work on the other (json) and vice/versa.
I've traced it down internally to the BeanSerializer being created for my model class, with no properties. I'm just not sure why this is. I've traced through the execution to see Jackson is running during the http convert process ... it's just ignoring all properties inside the object.
Here's my setup:
Maven:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>10</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.9.6</version>
<scope>runtime</scope>
</dependency>
module-info:
module stupid.example {
opens com.example.microservice.datasynchronizer;
opens com.example.microservice.datasynchronizer.model;
opens com.example.microservice.datasynchronizer.webflux to spring.beans, spring.core, spring.web ;
opens com.example.microservice.datasynchronizer.dao to spring.core ;
requires java.base ;
requires java.xml.bind ;
requires spring.boot;
requires spring.boot.autoconfigure;
requires spring.beans ;
requires spring.context ;
requires spring.core ;
requires spring.data.commons ;
requires spring.web ;
requires spring.webmvc ;
requires java.persistence ;
requires org.junit.jupiter.api;
requires spring.test;
requires spring.boot.test ;
}
Model class (latest, with jaxb annotations just in case):
#Entity
#XmlRootElement
public class Thingamajig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#XmlElement
private Long id;
#XmlElement
private String firstName;
#XmlElement
private String lastName;
public Thingamajig ( ) { ; }
public Thingamajig(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format("Thingamajig [id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
}
}
Controller:
#RestController
public class ThingamajigController {
#Autowired
private ThingamajigDao _dao ;
#GetMapping("/thing/{id}")
public Thingamajig getPerson(#PathVariable Long id) {
Optional<Thingamajig> found = _dao.findById(id) ;
return found.get() ;
}
#PostMapping ( "/thing" )
#ResponseStatus(HttpStatus.CREATED)
public void add(#RequestBody Thingamajig person) {
_dao.save(person) ;
}
}
Configuration:
#EnableWebMvc
#SpringBootApplication
public class DataSynchronizerApplication {
public static void main(String[] args) throws Throwable {
SpringApplication.run(DataSynchronizerApplication.class, args);
}
}
What the heck am I missing? Any help appreciated.
You simply forgot to define getters and setters in your Thingamajig class.
XML works because you have defined the annotations on the attributes but JSON serializer is looking for getters.
New Tag request: java-ee-8
It's got a new feature, called jsonb. With jsonb, I cannot get nested serialization working. See bold printed below.
So, I wrote a jaxrs-application. This application's got a messagebodywriter using jsonb:
final JsonbConfig defaultConfig = new JsonbConfig()
.withFormatting(Boolean.TRUE)
.withNullValues(Boolean.TRUE)
.withSerializers(
new QueryParamEntrySerializer(),
new ApiResponseDtoSerializer())
.withAdapters(new ResponseStatusJsonbAdapter());
final Jsonb jsonb = JsonbBuilder.create(defaultConfig);
ApiResponseDto is like following:
#Value.Immutable
#JsonbTypeSerializer(ApiResponseDtoSerializer.class)
public interface ApiResponseDto {
ResponseStatus status();
String message();
Optional<? extends Object> data();
}
ResponseStatus is an enumm and gets serialized via the above TypeAdapter just fine.
For this class I wrote the ApiResponseDtoSerializer.
#Provider
public class ApiResponseDtoSerializer implements JsonbSerializer<ImmutableApiResponseDto> {
#Override
public void serialize(
final ImmutableApiResponseDto obj,
final JsonGenerator generator,
final SerializationContext ctx) {
generator.writeStartObject();
ctx.serialize("status", obj.status(), generator);
ctx.serialize("data", obj.data(), generator);
ctx.serialize("message", obj.message(), generator);
generator.writeEnd();
}
}
Now the Optional data() shall contain an ImmutableSet of QueryParamEntry like this:
#Value.Immutable
#JsonbTypeSerializer(ImmutableQueryParamEntrySerializer.class)
public interface QueryParamEntry {
#Value.Parameter
String key();
#Value.Parameter
Optional<String> value();
}
The type adapter is this one:
#Provider
public class ImmutableQueryParamEntrySerializer implements JsonbSerializer<ImmutableQueryParamEntry> {
private static final Logger LOG = LoggerFactory.getLogger(ImmutableQueryParamEntrySerializer.class);
#Override
public void serialize(
final ImmutableQueryParamEntry obj,
final JsonGenerator generator,
final SerializationContext ctx) {
generator.writeStartObject();
LOG.debug("Writing: key = [{}].", obj.key());
ctx.serialize("key", obj.key(), generator);
ctx.serialize("value", obj.value(), generator);
generator.writeEnd();
}
}
The final output is:
{
"status": "success",
"data": [
{
"key": null,
"value": null
}
],
"message": "Returning query param values."
}
As you can see, the nested serialization did not work. Jsonb seems to find the correct type (because otherwise it wouldn't serialize an object at all). But even the log statement from my SerializerClass is never called.
Btw: You need Guava 22 and immutables.github.io to compile this code, and slf4j obviously:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.2.Final</version>
<scope>provided</scope>
</dependency>
<!-- JSON-P API -->
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.json.bind/javax.json.bind-api -->
<dependency>
<groupId>javax.json.bind</groupId>
<artifactId>javax.json.bind-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
So here is what it takes to make it work.
I got rid of the custom Serializers. As mentioned in my comment, they are broken before the unreleased version 1.0.3 anyway.
Instead, rename your methods to getStatus(), getMessage() and getData() (notice the get-Prefix).
For getData();, return just an Optional<Object>, not Optional<? extends Object>. Otherwise, immutables will refuse the special treatment of Optional.
After that, all just worked nicely.
I am making a rest service application with JAX-RS. Its for some project for school. For this project I need to use follow techniques:
• Maven
• JAX-RS
• CDI
• JPA - EJB
• JNDI
• Bean Validation
So now I already maded my domain "Cafes" with a Fake DB ("CafeStub") and a real DB using JPA ("CafeDB"). My domain also makes a little usage of CDI. (#Inject in the CafeService class ...)
Non I wanted to create my rest service, using JAX-RS. This worked fine:
My problem is when I try to use CDI again it fails and it gives an 500 exception, NullPointerException, "Severe: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container"
Full Stacktrace:
I don't know how to fix this, already searched a long time .. Hopefully somebody can help me :s
This is my "CafeController" class. Producing the rest service
Path("/cafes")
public class CafeController {
#Inject
private CafeFacade cafeFacade;
public CafeController() {
//this.cafeFacade = new CafeService();
}
#GET
#Produces("application/json")
public Response getCafes(){
try{
// test ........
ObjectMapper mapper = new ObjectMapper();
Cafe cafe = cafeFacade.getCafe(new Long(1));
String jsonInString = mapper.writeValueAsString(cafe);
return Response.status(200).entity(jsonInString).build();
}catch (JsonProcessingException jsonEx) {
System.out.println("Json Exception");
System.out.println(jsonEx.getMessage());
return null;
}
}
This one is the "CafeService" class, the one who implemented "CafeFacade"
public class CafeService implements CafeFacade {
#Inject
private CafeRepository cafeRepository;
public CafeService() {
//cafeRepository = new CafeStub();
//cafeRepository = new CafeDB("CafesPU");
}
#Override
public long addCafe(Cafe cafe) {
return this.cafeRepository.addCafe(cafe);
}
#Override
public Cafe getCafe(long cafeID) {
return this.cafeRepository.getCafe(cafeID);
}
Her you see the "CafeStub" class, the one who implemented "CafeRepository"
public class CafeStub implements CafeRepository {
private static Map<Long, Cafe> cafes;
private static long counter = 0;
public CafeStub() {
cafes = new HashMap<Long, Cafe>();
// adding some dara
this.addSomeData();
}
#Override
public long addCafe(Cafe cafe) {
if(cafe == null){
throw new DBException("No cafe given");
}
counter++;
cafe.setCafeID(counter);
cafes.put(cafe.getCafeID(), cafe);
return cafe.getCafeID();
}
#Override
public Cafe getCafe(long cafeID) {
if(cafeID < 0){
throw new DBException("No correct cafeID given");
}
if(!cafes.containsKey(cafeID)){
throw new DBException("No cafe was found");
}
return cafes.get(cafeID);
}
At least here you can see my pom.xml (dependencies from CafeService project) - web.xml (from CafeService project) and project structure ...
<dependencies>
<dependency>
<groupId>Cafes</groupId>
<artifactId>Cafes</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.19.4</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19.4</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.19.4</version>
</dependency>
</dependencies>
Thanks in advance ...
Cheers
Tom
A class annotated with just #Path does not mark the class as a CDI bean as it is not in the list of bean defining annotations in the CDI spec. Adding RequestScoped to the REST service marks it as a CDI bean so injection works as you've discovered.
This answer here lists the annotations which mark a class as a CDI bean.
Is #javax.annotation.ManagedBean a CDI bean defining annotation?
Solved .. RequestScoped did the trick.. Daimn searched so long for one annotation.
#RequestScoped
#Path("/cafes")
public class CafeController {
Still I don't understand why I need to use it.
#RequestScoped : CDI instantiates and manages the bean
-> I thought my bean.xml would have instantiates and manages the bean ?
There is an interface:
interface IEventListener
{
void onEvent(List <IEvent> events);
}
There is an event class:
class EventB
{
private final int id;
private final A a;
private final String somethingElse;
...
// constructors, getters
...
}
And there is a class to test:
class Doer
{
IEventListener eventListener;
void doSomething(Aaa a)
{
eventListener.onEvent(Arrays.asList(new EventA(1), new EventC(2)));
...
eventListener.onEvent(Arrays.asList(new EventB(42, a.getA(), "foo"), new EventA(3), new EventB(0, a.getA(), "bar")));
...
eventListener.onEvent(Arrays.asList(new EventC(4)));
}
}
The Doer is a code which I need to test, the method doSomething produces packs of events, and I need to test if it produces a particular event in some specific conditions.
More precisely I want to have a unit test which calls the method doSomething and checks that EventB is sent with "42" and A as from method argument a. All other events should be ignored.
To make such test I've only came up with solution involving quite verbose code with ArgumentCaptor, for-blocks, and magic boolean flags...
What is the best way to make a unit test for it? Maybe the code design is bad?
The design is correct, this is how you test it with Mockito:
import org.hamcrest.Matchers;
import org.mockito.Mockito;
public void firesEventsOnDoSomething() {
Listener listener = Mockito.mock(Listener.class);
Doer doer = new Doer(listener);
doer.doSomething(aaa);
Mockito.verify(listener).onEvent(
Mockito.argThat(
Matchers.hasItem(
Matchers.allOf(
Matchers.instanceOf(EventB.class),
Matchers.hasProperty("a", Matchers.equalTo(aaa.getA())),
// whatever you want
)
)
)
);
}
It's Mockito 1.9.0 and Hamcrest-library 1.2.1.
To use JUnit 4.10 together with Hamcrest-library 1.2.1 you should use junit:junit-dep:4.10 artifact, and exclude org.hamcrest:hamcrest-core from it:
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.10</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
If you are using JUnit4 you can try a paremetrized test. Here there is an example http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/.
If for each of your parameters you have to compare with a different result, you should better consider them as different test cases.
Create dummy implementation of EventListener:
class DummyEventListener implements EventListener {
private int expectedId;
DummyEventListener(int expectedId) {
this.expectedId = expectedId;
}
void onEvent(List <IEvent> events) {
for (IEvent event : events) {
if (!(event instanceof EventB)) {
continue;
}
EventB eb = (EventB)event;
assertEquals(expectedId, eb.getId());
// add more asserts here
}
}
}
Alternatively you can use one of available java mockup frameworks:
EasyMock, JMock, Mockito, JMockit etc.