Custom attribute factories for MeanBean EqualsMethodTester and HashCodeMethodTester - java

Is it possible to configure custom factories to generate values for the EqualsMethodTester and HashCodeMethodTester classes from org.meanbean.test? When I pass the Configuration which works for BeanTester to EqualsMethodTester, I get the following messages in the error traceback:
org.meanbean.factories.ObjectCreationException: Failed to create a value for property [demoUrl].
Failed to find suitable Factory for property=[demoUrl] of type=[class java.net.URL]. Please register a custom Factory.
org.meanbean.factories.ObjectCreationException: Failed to instantiate object of type [java.net.URL] due to NoSuchMethodException.
java.lang.NoSuchMethodException: java.net.URL.<init>()
(Both EqualsMethodTester and HashCodeMethodTester give this error. Adding "demoUrl" to the list of insignificantProperties for EqualsMethodTester().testEqualsMethod() makes no difference. Stepping through the code implies my URLFactory.create() isn't called at all.)
I do not see any options for passing the configuration into HashCodeMethodTester. I've skimmed documentation at the following sites, but have found neither a solution nor acknowledgement of the missing functionality: http://meanbean.sourceforge.net/docs/2.0.3/public/org/meanbean/test/EqualsMethodTester.html
http://meanbean.sourceforge.net/docs/2.0.3/public/org/meanbean/test/HashCodeMethodTester.html
http://meanbean.sourceforge.net/docs/2.0.3/public/org/meanbean/test/ConfigurationBuilder.html
http://meanbean.sourceforge.net/docs/2.0.3/Mean_Bean_2.0.3_User_Guide.pdf
(I'm using MeanBean v 2.0.3 and Java 1.8.)
I have the following class, using java.net.URL:
public class Product {
private String name;
private URL demoUrl;
public Product(){
super();
}
public int hashCode() {
return Objects.hash(getName(), whitehawkSKU);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
Product other = (Product) obj;
return Objects.equals(getName(), other.getName());
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public URL getDemoUrl() {
return demoUrl;
}
public void setDemoUrl(URL demoUrl) {
this.demoUrl = demoUrl;
}
}
To handle the URL field, I created a custom factory, as per meanbean: failed to test bean with arrays and it works for BeanTester but not for EqualsMethodTester:
import org.meanbean.lang.Factory;
import java.net.MalformedURLException;
import java.net.URL;
public class URLFactory implements Factory<URL> {
private static int counter = 0;
#Override
public URL create() {
String host = "http://test." + counter + ".url/";
try {
return new URL(host);
}
catch (MalformedURLException except) {
return null;
}
}
}
My test methods are as follows:
private Configuration configureMeanBeanTests() {
URLFactory urlFactory = new URLFactory();
return new ConfigurationBuilder()
.overrideFactory("demoUrl", urlFactory).build();
}
#Test
public void testAccessors() {
new BeanTester().testBean(Product.class, configureMeanBeanTests());
}
#Test
public void testEquals() {
new EqualsMethodTester().testEqualsMethod(
Product.class,
configureMeanBeanTests(),
"name",
"demoUrl"
);
}
#Test
public void testHashCode() {
new HashCodeMethodTester().testHashCodeMethod(Product.class);
}
What am I missing?

It looks like the EqualsMethodTester().testEqualsMethod() needs a EquivalentFactory in that particular case due to the use java.net.URL that does not provide a default empty constructor. So when BasicNewObjectInstanceFactory.create() is called for java.net.URL the call the clazz.getDeclaredConstructor() throw an exception Method threw 'java.lang.NoSuchMethodException' exception..
Basically you just have to implement a EquivalentFactory.
An anonymous implementation could be:
private EquivalentFactory<Product> productEquivalentFactory = new EquivalentFactory<Product>() {
#Override
public Product create() {
Product p = new Product();
try {
p.setDemoUrl(new URL("http://test.1.url/"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
p.setName("test");
return p;
}
};
It has to be used with the custom configuration that you already have:
new EqualsMethodTester().testEqualsMethod(productEquivalentFactory, configureMeanBeanTests(), "demoUrl");`
For the hashcode just use the equivalent factory and it does the job.
I tested it and it is working.

Related

Replacement for isInstance() method when deploying to web in libgdx

I'm making a game with libGDX that I want to export to HTML using Gradle. The issue comes when I use this method to get a list of actors. Apparently isInstance() and isInstanceOf are not compatible with GWT so I'm looking for a way to get around this. Gradle tell me isInstance is not defined. It runs fine on desktop.
public static ArrayList<BaseActor> getList(Stage stage, String className) {
ArrayList<BaseActor> list = new ArrayList<BaseActor>();
Class theClass = null;
try {
theClass = ClassReflection.forName("com.mygdx.game.actors." + className);
} catch (Exception error) {
error.printStackTrace();
}
for (Actor a : stage.getActors()) {
if (theClass.isInstance(a))
list.add((BaseActor) a);
}
return list;
}
The Actor class has a user object property (getUserObject()/setUserObject()) that you can use to attach data. You could make your BaseActor use this as a class tag property, and use an abstract method so you won't forget to add it to any of your Actor implementations.
abstract class BaseActor {
//...
public BaseActor() {
setUserObject(getClassTag());
//...
}
protected abstract String getClassTag();
}
class SomeSpecificActor extends BaseActor {
public SomeSpecificActor () {
super();
//...
}
#Override
protected String getClassTag() {
return "SomeSpecificActor";
}
}
public static ArrayList<BaseActor> getList(Stage stage, String classTag) {
ArrayList<BaseActor> list = new ArrayList<BaseActor>();
for (Actor a : stage.getActors()) {
if (classTag.equals(a.getUserObject()))
list.add((BaseActor) a);
}
return list;
}

How to unit test side effecting logic

I have a following code
public class Component extend Framework {
private Integer someInt;
private String someString;
public Integer getSomeInt() {
return someInt;
}
public String getSomeString() {
return someString;
}
public void activate() {
Integer tempInt = (Integer)getProperties("key"); // From Framework
if (tempInt == null) {
tempInt = (Integer)getRequest().getProperties("key"); // From Framework
}
if(tempInt == null)
tempInt = (Integer)getBind().getProperties("key"); // From Frameowrk
someString = makeServiceCall("http://.....?key=tempInt");
}
}
Basically activate() method is called by the framework in order to access internal state of the framework to construct Component object. activate() is sort of like a setter for the Component object.
If I were to unit test the code above, what would be the best way to do it without having to have framework running?
One way would be to mock out Component class and stub the super.getProperties... calls, however if we mock the class in question, what is the point of testing to begin with?
I will show how to test one edge case
void testServiceCallWithNoKeyPropertyFound() {
Component componentUnderTest = new Component() {
Integer getProperties(String key) {
return null; // property should not be found
}
Request getRequest() {
return new Request(...); //this request should not contain a property named "key",
}
Bind getBind() {
return new Bind(...); //this bind should not contain a property named "key"
}
String makeServiceCall(String url) {
if (url.endsWith("null")) {
return success;
}
throw new AssertionError("expected url ending with null, but was " + url);
}
};
componentUnderTest.activate();
assertThat(componentUnderTest.getSomeString(), equalTo("success"));
}
Using Mockito (spys) can make this example much more concise. But this would hide the principles how to design the test.
There are some more edge cases:
void testServiceCallWithPropertyFoundInComponent() ...
void testServiceCallWithPropertyFoundInRequest() ...
void testServiceCallWithPropertyFoundInBind() ...
Use Mockito.
Spy the Component class and mock the methods getRequest() and getBind().
Finally, call the activate() method directly from your unit test.
I think it could be a smell of bad design. Maybe you should consider composition instead of inheritance? It would be more testing friendly and more objective. Why Component is inheriting from Framework class?
public class Component {
private int someInt;
private String someString;
private Framework framework;
public Component(Framework framework) {
this.framework = framework
}
public int getSomeInt() {
return someInt;
}
public String getSomeString() {
return someString;
}
public void activate() {
int tempInt = framework.getProperties("key"); // From Framework
if (tempInt == null) {
tempInt = framework.getRequest().getProperties("key"); // From Framework
}
if(tempInt == null)
tempInt = framework.getBind().getProperties("key"); // From Frameowrk
someString = makeServiceCall("http://.....?key=tempInt");
}
}

How to remove try/catch repetitions in class methods?

I have RESTeasy service. And have implemented simple error handling on methods using try catch and feel something is not very well with it. I've noticed try catch repetition on all my methods. So I want ask way how to avoid repetition (to reduce code size) of try catch but not lost functionality.
#Path("/rest")
#Logged
#Produces("application/json")
public class CounterRestService {
#POST
#Path("/create")
public CounterResponce create(#QueryParam("name") String name) {
try {
CounterService.getInstance().put(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#POST
#Path("/insert")
public CounterResponce create(Counter counter) {
try {
CounterService.getInstance().put(counter);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
#DELETE
#Path("/delete")
public CounterResponce delete(#QueryParam("name") String name) {
try {
CounterService.getInstance().remove(name);
return new CounterResponce();
} catch (Exception e){
return new CounterResponce("error", e.getMessage());
}
}
... // other methods with some try catch pattern
response
public class CounterResponce {
private String status;
#JsonSerialize(include=Inclusion.NON_NULL)
private Object data;
public CounterResponce() {
this.status = "ok";
}
public CounterResponce(Object o) {
this.status = "ok";
this.data = o;
}
public CounterResponce(String status, Object o){
this.status = status;
this.data = o;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
exceptions source
public class CounterService {
private Map<String, StatisticCounter> counters = new HashMap<String, StatisticCounter>();
private static CounterService instance = null;
protected CounterService() {}
public static CounterService getInstance() {
if(instance == null) {
instance = new CounterService();
}
return instance;
}
public StatisticCounter get(String name){
StatisticCounter c = counters.get(name);
if(c == null)throw new IllegalArgumentException("Counter "+name+" not exist");
return c;
}
public void put(String name){
if(name==null)throw new IllegalArgumentException("null can`t be as name");
if(counters.get(name)!=null)throw new IllegalArgumentException("Counter "+name+" exist");
counters.put(name, new Counter(name));
}...
The comments in your question are pointing you in a good direction. Since the answers do not mention it, I'll summarize the general idea in this answer.
Extending WebApplicationException
JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. By extending WebApplicationException, you can create application specific exceptions that build a HTTP response with the status code and an optional message as the body of the response.
The following exception builds a HTTP response with the 404 status code:
public class CustomerNotFoundException extends WebApplicationException {
/**
* Create a HTTP 404 (Not Found) exception.
*/
public CustomerNotFoundException() {
super(Responses.notFound().build());
}
/**
* Create a HTTP 404 (Not Found) exception.
* #param message the String that is the entity of the 404 response.
*/
public CustomerNotFoundException(String message) {
super(Response.status(Responses.NOT_FOUND).
entity(message).type("text/plain").build());
}
}
WebApplicationException is a RuntimeException and doesn't need to the wrapped in a try-catch block or be declared in a throws clause:
#Path("customers/{customerId}")
public Customer findCustomer(#PathParam("customerId") Long customerId) {
Customer customer = customerService.find(customerId);
if (customer == null) {
throw new CustomerNotFoundException("Customer not found with ID " + customerId);
}
return customer;
}
Creating ExceptionMappers
In other cases it may not be appropriate to throw instances of WebApplicationException, or classes that extend WebApplicationException, and instead it may be preferable to map an existing exception to a response.
For such cases it is possible to use a custom exception mapping provider. The provider must implement the ExceptionMapper<E extends Throwable> interface. For example, the following maps the JAP EntityNotFoundException to a HTTP 404 response:
#Provider
public class EntityNotFoundExceptionMapper
implements ExceptionMapper<EntityNotFoundException> {
#Override
public Response toResponse(EntityNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
When an EntityNotFoundException is thrown, the toResponse(E) method of the EntityNotFoundExceptionMapper instance will be invoked.
The #Provider annotation declares that the class is of interest to the JAX-RS runtime. Such class may be added to the set of classes of the Application instance that is configured.
Introduce a private method such as "apply" which can take function as parameter if you use Java 8. This method will have the error handling and/or mapping, response mapping and response generation code centralized.
From create and delete methods, invoke this apply method and pass the desired counter operation you wish to perform as a lambda expression.

Adding methods to AuthenticatedWebSession in Wicket 7 by extension

I'm using Wicket 7 and extending AuthenticatedWebSession as a class called BasicAuthenticatedSession. While I'm doing this, I'd like to add a method that returns some additional information about the authenticated user.
In BasicAuthenticatedSession#authenticate, I get a Sysuser object which is a wrapper for a user in the database. I use some of the information in this object for the authentication, but want to have access to all of the info (firstname, lastname, etc.) throughout the session.
I was expecting to be able to create a new method call getUser which would return this database object to the caller.
However, this method, even though declared public, isn't visible when attempting to call it. I'm not sure if this is something to do with Wicket, or just a general misunderstanding on my part how inheritance works. ;)
BasicAuthenticatedWebSession.java
public class BasicAuthenticatedWebSession extends AuthenticatedWebSession {
public BasicAuthenticatedWebSession(Request request) {
super(request);
}
#Override
protected boolean authenticate(String username, String password) {
Sysuser[] sysusers;
try {
SysuserCriteria userCriteria = new SysuserCriteria();
userCriteria.username.eq(username);
sysusers = Sysuser.listSysuserByCriteria(userCriteria);
} catch (PersistentException e) {
e.printStackTrace();
return false;
}
if (sysusers.length == 0) {
return false;
}
this.username = username;
this.userid = sysusers[0].getId();
return password.compareTo(sysusers[0].getPasswd()) == 0;
}
public Roles getRoles() {
Roles roles = new Roles();
Sysuser[] sysusers;
if (isSignedIn()) {
roles.add("SIGNED_IN");
}
try {
SysuserCriteria sysuserCriteria = new SysuserCriteria();
sysuserCriteria.username.eq(username);
sysusers = Sysuser.listSysuserByCriteria(sysuserCriteria);
for (Object sysuser : sysusers) {
SysroleSetCollection sysroles = ((Sysuser) sysuser).sysrole;
for (Sysrole sysrole : sysroles.toArray()) {
roles.add(sysrole.getRolename().toUpperCase());
}
}
} catch (PersistentException e) {
e.printStackTrace();
}
return roles;
}
public Sysuser getSysuser() {
return sysuser;
}
}
Test.java This class fails to compile as the getSysuser method in BasicAuthenticatedSession is not found.
public class Test {
public Test() {
}
public void foo {
if(BasicAuthenticatedSession.get().isSignedIn()) {
Sysuser sysUser = BasicAuthenticatedSession.get().getSysuser();
System.out.println(sysuser.getFirstname);
}
}
}
Wicket project require specific "override" of static methods, I guess that You return original wicket API session. Edited copy from my project (session is Your classname)
public class BasicAuthenticatedWebSession extends AuthenticatedWebSession {
public static BasicAuthenticatedWebSession get() {
return (BasicAuthenticatedWebSession ) Session.get();
}
...
}
and in XxxxxApplication class
public class MyProject extends AuthenticatedWebApplication
{
...
#Override
public Session newSession(Request request, Response response) {
return new BasicAuthenticatedWebSession (request);
}
}

Creating a HashMap of type <String , Object>

In a previous post Creating a ToolTip Managed bean
I was able to create a manged bean to collect and display tooltip text with only a single lookup and store them in an Application Scope variable. This has worked great.
I am on the rather steep part of the JAVA learning curve so please forgive me.
I have another managed bean requirement to create a HashMap Application Scope but this time it needs to be of a type String, Object. The application is where I have a single 'master' database that contains most of the code, custom controls, and XPages. This Master Database will point to One or More application databases that will store the Notes Documents specific to the application in question. So I have created in the Master a series of Application Documents that specify the RepIDs of the Application, Help and Rules databases specific to the Application along with a number of other pieces of information about the Application. This should allow me to reuse the same custom control that will open the specific DB by passing it the Application Name. As an example the Master Design DB might point to "Purchasing", "Customer Complaints", "Travel Requests" etc.
The code below works to load and store the HashMap, but I am having trouble retrieving the the data.
The compiler shows two errors one at the public Object get(String key) method and the other at mapValue = this.internalMap.get(key); in the getAppRepID method I think that it is mainly syntax but not sure. I have commented the error in the code where it appears.
/**
*This Class makes the variables that define an application within Workflo!Approval
*available as an ApplicationScope variable.
*/
package ca.wfsystems.wfsAppUtils;
import lotus.domino.Base;
import lotus.domino.Session;
import lotus.domino.Database;
import lotus.domino.View;
import lotus.domino.NotesException;
import lotus.domino.ViewColumn;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;
import lotus.domino.Name;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import com.ibm.xsp.extlib.util.ExtLibUtil;
/**
* #author Bill Fox Workflo Systems WFSystems.ca
* July 2014
* This class is provided as part of the Workflo!Approval Product
* and can be reused within this application.
* If copied to a different application please retain this attribution.
*
*/
public abstract class ApplicationUtils implements Serializable, Map<String, Object> {
private static final long serialVersionUID = 1L;
private Session s;
private Name serverName;
private String repID;
private String thisKey;
private ViewEntryCollection formVECol;
private Vector formNames;
private Database thisDB;
private Database appDB;
private View appView;
private View formView;
private ViewEntry formVE;
private ViewEntry tFormVE;
private ViewEntry ve;
private ViewEntry tVE;
private ViewEntryCollection veCol;
private final Map<String, Object> internalMap = new HashMap<String, Object>();
public ApplicationUtils() {
this.populateMap(internalMap);
}
private void populateMap(Map<String, Object> theMap) {
try{
s = ExtLibUtil.getCurrentSession();
//serverName = s.createName(s.getServerName());
thisDB = s.getCurrentDatabase();
appView = thisDB.getView("vwWFSApplications");
veCol = appView.getAllEntries();
ve = veCol.getFirstEntry();
ViewEntry tVE = null;
while (ve != null) {
rtnValue mapValue = new rtnValue();
tVE = veCol.getNextEntry(ve);
Vector colVal = ve.getColumnValues();
thisKey = colVal.get(0).toString();
mapValue.setRepID(colVal.get(2).toString());
// ...... load the rest of the values .......
theMap.put(thisKey, mapValue);
recycleObjects(ve);
ve = tVE;
}
}catch(NotesException e){
System.out.println(e.toString());
}finally{
recycleObjects(ve, veCol, appView, tVE);
}
}
public class rtnValue{
private String RepID;
private String HelpRepID;
private String RuleRepID;
private Vector FormNames;
public String getRepID() {
return RepID;
}
public void setRepID(String repID) {
RepID = repID;
}
public String getHelpRepID() {
return HelpRepID;
}
public void setHelpRepID(String helpRepID) {
HelpRepID = helpRepID;
}
public String getRuleRepID() {
return RuleRepID;
}
public void setRuleRepID(String ruleRepID) {
RuleRepID = ruleRepID;
}
public Vector getFormNames() {
return FormNames;
}
public void setFormNames(Vector formNames) {
FormNames = formNames;
}
}
public void clear() {
this.internalMap.clear();
this.populateMap(this.internalMap);
}
public boolean containsKey(Object key) {
return this.internalMap.containsKey(key);
}
public boolean containsValue(Object value) {
return this.internalMap.containsValue(value);
}
public Set<java.util.Map.Entry<String, Object>> entrySet() {
return this.internalMap.entrySet();
}
public Object get(String key) {
//error on Object get Method must return a result of type Object
try {
if (this.internalMap.containsKey(key)) {
return this.internalMap.get(key);
}
} catch (Exception e) {
System.out.println(e.toString());
rtnValue newMap = new rtnValue();
return newMap;
}
}
public boolean isEmpty() {
return this.internalMap.isEmpty();
}
public Set<String> keySet() {
return this.internalMap.keySet();
}
public Object put(String key, Object value) {
return this.internalMap.put(key, value);
}
public Object remove(Object key) {
return this.internalMap.remove(key);
}
public int size() {
return this.internalMap.size();
}
public Collection<Object> values() {
return this.internalMap.values();
}
public void putAll(Map<? extends String, ? extends Object> m) {
this.internalMap.putAll(m);
}
public String getAppRepID(String key){
/*get the Replica Id of the application database
* not sure this is the correct way to call this
*/
rtnValue mapValue = new rtnValue();
mapValue = this.internalMap.get(key);
//error on line above Type Mismatch: can not convert Object to ApplicationUtils.rtnValue
String repID = mapValue.getRepID();
}
public static void recycleObjects(Object... args) {
for (Object o : args) {
if (o != null) {
if (o instanceof Base) {
try {
((Base) o).recycle();
} catch (Throwable t) {
// who cares?
}
}
}
}
}
}
For the get() method, the way I handle that kind of situation is create a variable of the correct data type as null, in my try/catch set the variable, and at the end return the variable. So:
Object retVal = null;
try....
return retVal;
For the other error, if you right-click on the error marker, it might give you the opportunity to cast the variable to rtnValue, so:
mapValue = (rtnValue) this.internalMap.get(key)
If you haven't got it, Head First Java was a useful book for getting my head around some Java concepts. It's also worth downloading the FindBugs plugin for Domino Designer from OpenNTF. It will identify errors as well as bad practices. Just ignore the errors in the "local" package!
The problem is that there is an execution path that do not return nothing
public Object get(String key) {
//error on Object get Method must return a result of type Object
try {
if (this.internalMap.containsKey(key)) { // false
return this.internalMap.get(key);
}
} catch (Exception e) {
System.out.println(e.toString());
rtnValue newMap = new rtnValue();
return newMap;
}
}
if key is not present in the internalMap, nothing is thrown, then that method do not return anything.
To fix the problem, return the newMap at the end.
public Object get(String key) {
//error on Object get Method must return a result of type Object
try {
if (this.internalMap.containsKey(key)) {
return this.internalMap.get(key);
}
} catch (Exception e) {
System.out.println(e.toString());
}
rtnValue newMap = new rtnValue();
return newMap;
}
You can inline the return to save the allocation (which is what the compiler will do anyway). I didn't do it just to make it clear in the example.
But still you have a compiler error in getAppRepID method. You are expecting a rtnValue but you send back an Object. You must cast there.
The appropriate way to handle this is, if you know that all values are of a given type, create the map with the proper type.
Have you tried making your internalMap a map of rtnValue instances (so )?

Categories

Resources