Calling method in java 8 - java

I have a method,
private String createSubjectColumnForOutgoing(Message message)
{
//TODO : Changes for blocking messages of spam users
if(message.getReceiverEnvelope() != null && message.getReceiverEnvelope().getUser() != null && message.getReceiverEnvelope().getUser().isBlocked())
{
return I18N.IN_REVIEW_BY_TEAM.msg();
}
return StringUtils.deSanitizeSpecialCharacters(message.getSubject());
}
and this method is called like this,
case OUTGOING:
table.addGeneratedColumn(I18N.MESSAGETABLE_HEADER_SUBJECT.msg(), this::createSubjectColumnForOutgoing);
break;
And the constructor in the class are,
public MessageTable(Directory directory, boolean withFilter, Device device)
{
this(directory, new FilterConfiguration(withFilter), device);
}
public MessageTable(Directory directory, FilterConfiguration filterConfiguration, Device device)
{
Objects.requireNonNull(directory);
Objects.requireNonNull(device);
this.directory = directory;
dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(LocaleAware.super.getLocale());
tableFooter = createTableFooter();
openButton = createOpenButton();
newButton = createNewButton();
messageTable = createTable(device);
tableFooter.addComponent(newButton, 0);
tableFooter.addComponent(openButton, 1);
final VerticalLayout layout = new VerticalLayout();
layout.addComponent(createFilterComponent(filterConfiguration));
layout.addComponents(tableFooter, messageTable);
layout.setComponentAlignment(tableFooter, Alignment.MIDDLE_LEFT);
rootLayout = layout;
setCompositionRoot(rootLayout);
}
When calling this method createSubjectColumnForOutgoing there is no parameter passed, and it is working perfectly. I am not able to understand from where data is coming in Message object. I googled but not able to understand it. Please help. Thanks in advance.
Code of addGeneratedColumn
public void addGeneratedColumn(Object id, Function<BEANTYPE, ?> generatedColumn)
{
String header = null;
if(id instanceof String)
{
header = (String) id;
}
addGeneratedColumn(header, id, (source, itemId, columnId) -> generatedColumn.apply(itemId));
}

this::createSubjectColumnForOutgoing is a method reference, not an execution of the createSubjectColumnForOutgoing method.
The table.addGeneratedColumn() method, to which you pass the method reference, may be calling the method of the functional interface implemented by this method reference. If it does, it passes a Message instance to it.
You haven't included the code of addGeneratedColumn(), so I don't know what type of functional interface it expects (perhaps a Function).
EDIT:
Following your edit, Function<BEANTYPE, ?> generatedColumn is the functional interface implemented by the method reference you pass to addGeneratedColumn(). This means that generatedColumn.apply(itemId) is the statement that executes the createSubjectColumnForOutgoing() method, and you can see that itemId is passed to the method. This means that itemId must be a Message instance.
Note that addGeneratedColumn(Object id, Function<BEANTYPE, ?> generatedColumn) doesn't execute the createSubjectColumnForOutgoing() method either. It passes a functional interface (implemented by a lambda expression) that can execute that method to a second addGeneratedColumn method.

Related

Why a WrongMethodTypeException from MethodHandle? Is my object type incorrect?

I have encountered a problem while I am trying to switch my event system from reflection to MethodHandle.
I am using an event bus (version 3.0.0) by KyoriPowered on Github (https://github.com/KyoriPowered/event).
My code is following:
public class EventExecutorFactory implements EventExecutor.Factory<Event, Listener> {
#Override
public #NonNull EventExecutor<Event, Listener> create(#NonNull Object object, #NonNull Method method) throws Exception { // object is Listener
method.setAccessible(true);
Class<? extends Event> actualEventType = method.getParameterTypes()[0].asSubclass(Event.class);
MethodHandle handle = MethodHandles.lookup().unreflect(method);
return new EventExecutor<Event,Listener>() {
#Override
public void invoke(#NonNull Listener listener, #NonNull Event event) throws Throwable {
if (!actualEventType.isInstance(event)) return; // many different event types defined in my system, so I should check it first.
handle.invoke(actualEventType.cast(event)); // WrongMethodTypeException thrown here
}
}
}
}
I expected this to work fine, but the result is:
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(,UserOnlineEvent)void to (Event)void
UserOnlineEvent is the event type that used in test.
The problem is that I cannot get the real type of the event.
Edit: This problem has been solved. I should use two arguments.
just add the listener as the first argument to handle.invoke, and it works.
According to your message , I find the code in JDK. at MethodHandle#asTypeUncached
/*non-public*/
MethodHandle asTypeUncached(MethodType newType) {
if (!type.isConvertibleTo(newType))
throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true);
}
it's clear, I guess parameter type is wrong. if debug , you will find it.

Unexplainable Singleton / Picocli behaviour

I'm writing some code and I can't figure out what's going on with the bug I have. I hope someone here can give me some answers. Here is my code (the relevant part):
public class AppData implements Callable<Integer> {
private static AppData appData = new AppData();
private AppData() {
System.out.println("AppData-Constructor");
}
public static AppData getInstance() {
return appData;
}
#Override
public Integer call() throws Exception { // your business logic goes here...
return 0;
}
private boolean _validate;
public boolean validate() {
return _validate;
}
#Option(names = { "--validate" }, description = "", defaultValue = "false", hidden = false, interactive = false, paramLabel = "", required = false, type = boolean.class)
public void set_validate(boolean validate) {
System.out.println("Set Validate: " + validate);
this._validate = validate;
if(validate)
{
System.out.println("\nBeginne Programmvalidierung\n");
Path tmp = null;
try {
// Doing some validation stuff
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
As you can see my class is a singleton. The annotation is from picoli, which I use to parse the command line arguments. The System.out-calls are for debugging. This is the behaviour I can't explain:
When I start my app with e.g. "-h" as argument, I get the help printed just fine. The System.out.printlnshow that the singleton is created and that set_validate() is called with the default value. But that changes when I use --validate as an argument.
For some reason, the constructor and default set are called twice in a row. After that, set_validate()
is called with true (as it should). However, it seems that the first call sets the static instance variable, while the last call with true is done on the second instance (my theory). As a consequence, when I check the state of _validate with validate() on my singleton instance from my main method (in another class) I get false, as it wasn't set in the right instance.
I used a search engine to check:
The constructor is not called anywhere except for the static singleton instance (as expected, since it's private).
_validate is not accessed anywhere except the code I posted.
set_validate() is not called anywhere. Only Picocli calls it.
I don't know what to check next. Any ideas?
Regards
Thorsten
EDIT:
AppData is one of multiple classes holding the data. They are all collected in one big class for Picocli like this:
class Data
{
#AddGroup(...)
AppData appData = AppData.getInstance();
#AddGroup(...)
FooData fooData = FooData.getInstance();
#AddGroup(...)
BarData barData = BarData.getInstance();
}
It's used like this in my main method:
Data data = new Data();
CommandLine cmd = new CommandLine(data);
cmd.parseArgs(args);
I suspect (but can only guess, since that part of the code is not shown) that AppData is either a subcommand of another command, or that the application uses picocli like this:
int exitCode = new CommandLine(AppData.class).execute(args);
In both cases, picocli will create an instance of AppData using reflection. The instance created by picocli is the instance populated from the command line values. This is a different instance than the one returned by AppData::getInstance.
One way to ensure there is only one instance is to pass the singleton instance to picocli. For example:
AppData singleton = AppData.getInstance();
int exitCode = new CommandLine(singleton).execute(args);
System.out.println("validate=" + singleton.validate());
(If AppData is a subcommand there are other ways to access the instance that picocli created, like the #Spec annotation to inject the picocli model, and calling CommandSpec::userObject() getter on that to get the AppData instance.)
Now, the other question is: why does the set_validate method get invoked twice?
As of version 4.2, picocli will first call #Option-annotated methods with the default value, before parsing the command line parameters. So the set_validate method is first invoked with the default value, and then called again with the value specified on the command line.
(From version 4.3 (to be released soon), the default value will only be set if the value is not specified on the command line, so from version 4.3 the set_validate method will only be invoked once.)

Mokito, Mocking method behavior

I am fairly new to automated testing and I have been having some trouble with mocking a class with mockito. Basically what I am trying to do is make use of an interface that is being sent to a method, when this method (Request(Response)) is called I want mockito to intervene and call a method from the interface passing an object as a param (callback.OnSuccess(Obj)). Here is an example of what I mean, I will start off with my production code I have taken out everything that isnt needed:
ServerRequest class
public void Request(ResponseInterface callback){
//The contents of this class isnt really important as I do not wish to use any of it
//but in general this makes a request to the server and if the request is a success then
Object obj = ProcessResponse(Response);
callback.OnSuccess(obj);
//otherwise
Object obj = ProcessResponse(Response);
callback.OnError(obj);
}
ResponseInterface
public interface ResponseInterface(){
void OnSuccess(Object resp);
void OnError(Object resp);
}
MainActivity
public void MakeRequest(){
ServerRequest.Request(new ResponseInterface(){
#Override
public void OnSuccess(Object objResponse){
//do something to show user the request was successful depending on the current activity
}
#Override
public void OnError(String e){
//do something depending on the current activity
})
}
So far I have tried multiple methods, the best I could come up with is in the code below, but as I am sure you can tell from the post it did not work but I will leave it here as it might give somebody a better idea of what I am trying to do.
ServerRequest mockReq = mock(ServerRequest.class);
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
System.out.println("Running first time");
Object[] arguments = invocation.getArguments();
ResponseInterface inter = (ResponseInterface) arguments[2];
Object obj = "Already taken";
inter.OnSuccess(obj);
return null;
}
}).when(mockReq).InformationRequest(ArgumentMatchers.anyMap(),anyString(),ArgumentMatchers.<ServerInterface>any());
Any help on this matter would be greatly appreciated as I have no clue what I am doing.
In case anybody else is ever trying to achieve something similar I have figured out how to call the method in the interface sent through the mocked method.
So to start off I created setup method annotated with before (not necessarily needed you can place this just before your test in the same method). Then I began setting up everything needed to achieve my goals, here is the setup required.
//class to be mocked
#Mock
ServerRequest mockReq;
#Before
public void setup(){
//get the activity instance
Registration reg = mActivityRule.getActivity();
//make sure the actual method to be mocked does nothing, By default it should do nothing anyway but for some reason not for me
doNothing().when(mockReq).InformationRequest(ArgumentMatchers.anyMap(),anyString(),ArgumentMatchers.<ServerInterface>any());
//set up an argument catcher
captor = ArgumentCaptor.forClass(ServerInterface.class);
//inject the mock into the activity
reg.serverRequest = mockReq;
}
Next up in my test method the mocked method should be called when the submit button is clicked, in which case I verify the mocked method was actually called and capture the data sent to it, then I use the data in what ever manner I wish.
//click the button
onView(withId(R.id.SubmitBtn)).perform(scrollTo(), click());
//check to see if method was called then capture the interface
verify(mockReq).InformationRequest(ArgumentMatchers.anyMap(),anyString(),captor.capture());
//get the interface
ServerInterface serverInter = captor.getValue();
Object obj = "Already taken";
//make use of the interface
serverInter.OnSuccess(obj);

NullPointerException when creating new String

SOLUTION
I was adding a new instance of A to the list: aList.add( new A() ), whose name property is of course null, instead of adding the actual initialized instance. Sorry for the dumb question.
I have this A class of ProjectA which overrides its toString method to return a clone of its name property, like this:
public class A {
private String name;
#Override
public String toString() {
return new String(name);
}
}
I then export this library to a jar and import it into ProjectB and when I call a.toString() I get a NullPointerException that says there is an error exactly on the return line: return new String(name);.
However, if I put it like this:
public class A {
private String name;
#Override
public String toString() {
return name;
}
}
I don't get any exception but the String returned is null.
I built the jar (ProjectA) using Eclipse and imported it into ADT (ProjectB - Eclipse too).
NOTE:
I omitted the getters/setters intentionally for the sake of simplicity, but they're in there in the original code and I'm pretty sure I set the name property way before calling the toString() method. In fact, if I call the getName() method, the name is returned perfectly fine, but I'm using lists and I need the toString() method.
This is the part of the code where the List of A objects is created (ProjectA too):
ArrayList<A> aList = new ArrayList<Categoria>();
for (int i = 0; i < random.nextInt(3)+1; i++) {
A a = new A();
a.setId(0);
a.setName("Test name");
a.setDescription("Test desc.");
aList.add(a);
Log.d("app", "Created object A: "+a.getName()); // The name is displayed OK here
}
aList.trimToSize();
And this is the exact part of the code where the toString() method is called (ProjectA):
new ArrayAdapter<A>(
actionBar.getThemedContext(),
android.R.layout.simple_list_item_1,
android.R.id.text1,
DataAccess.getAList() // The ArrayAdapter class calls the toString method to populate a list
)
As you could see, I in fact verify the content of the name property via the getName() method and it is okay. I have to mention that the first approach (the on which uses new String(name), without an finals nor null checks) worked flawlessly on another project.
This is the (relevant part of the) DataAccess class:
public final class DataAccess {
private static final Data data;
public static Arrayist<A> getAList() {
return this.data.getAList();
}
}
When you invoke new String(name); it invokes the overloaded parameterized constructor of String shown below :
public String(String original) {
int size = original.count;
........
.........
}
As you can see the first line in the code tries to compute the length of the String passed to the constructor. Since in your case the String is null invoking the member variable count on that null reference throws NullPointerException.
Note : In the code where you create AList, i dont see you adding the object to the list i.e. AList.add(a); is missing
return new String(name);
Would fail on name being null. It could happen on A a = new A(); System.out.println(a):.
The used constructor String(String) is a relict of the beginning of Java, reminiscent of the C++ copy constructor.
In Java String is immutable, and Java does not need the copy constructor.
Two solutions:
return String.valueOf(name); // Would return "null" for null.
return name == null ? "" : name;
As far as the exception goes you are getting a null pointer as already explained by #Kakarot.
This line blows up
original.count
But if you want to save yourself from null checking etc and at the same time have a efficient toString() method than user some thing like this.
public class A {
private String name = null;
private String address = " Some place";
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
return sb.append(name).append(address).toString();
}
}
Using string builder is efficient and you can see the output for the above toString() even with null values.
null Some place
In java new String(null) results into NullPointerException.
#Override
public String toString() {
if(name!=null){
return name;
}else{
return "";
}
}

Can an object know from which object its method is called?

In Moritz Haarmann's Blog I found an example of usage of Bonjour by Java. Here is the code taken from there:
public class ServiceAnnouncer implements IServiceAnnouncer, RegisterListener {
private DNSSDRegistration serviceRecord;
private boolean registered;
public boolean isRegistered(){
return registered;
}
public void registerService() {
try {
serviceRecord = DNSSD.register(0,0,null,"_killerapp._tcp", null,null,1234,null,this);
} catch (DNSSDException e) {
// error handling here
}
}
public void unregisterService(){
serviceRecord.stop();
registered = false;
}
public void serviceRegistered(DNSSDRegistration registration, int flags,String serviceName, String regType, String domain){
registered = true;
}
public void operationFailed(DNSSDService registration, int error){
// do error handling here if you want to.
}
}
I have a question about the "serviceRegistered" method. As far as I understand it is called during (or after) registration of the service (and it sets variable "registered" to be equal to "true"). But what is not clear to me is how exactly it is called. Because the service is registered by the method "registerService". This method, in its turn, calls "DNSSD.register". And, as far as I understand, the "DNSSD.register" will call the "serviceRegister" method of the "ServiceAnnouncer" class. But how "DNSSD.register" knows that it needs to call a method of the "ServiceAnnouncer" class? Can "DNSSD.register" know that it is called from a particular class (in this case "ServiceAnnouncer" class)?
The ServiceAnnouncer has passed itself as last argument of the DNSSD.register() method, which in turn is apparently expecting any instance of RegisterListener. This way the DNSSD can have a direct handle to the ServiceAnnouncer instance.
It seems that this class is a listener - namely RegisterListener. It has been registered as a listener in DNSSD by passing itself to the register(..) method.
For more information read about the Observer pattern.

Categories