I am using this library which is a CalendarView. https://github.com/kizitonwose/CalendarView
In the sample code there is the following code which attaches a Scroll Listener to the CalendarView
calendarView.monthScrollListener = { // etc}
I am unsure how to translate this to Java, I try the following but the "MonthScrollListener" class is nowhere to be found, its like it want some other type but I cannot find the type. Everything else has worked so far when translating the Kotlin to Java but I cannot see how this might work
mBinding.calendarView.setMonthScrollListener(new MonthScrollListener(){ // etc});
What should I pass into the setMonthScrollListener() method?
Edit: when I "ctrl click" on the setMonthScrollListener() it takes me into the CalendarView class and there is the following line:
public final var monthScrollListener: com.kizitonwose.calendarview.ui.MonthScrollListener? /* = ((com.kizitonwose.calendarview.model.CalendarMonth) -> kotlin.Unit)? */ /* compiled code */
So I try explicitly referencing the MonthScrollListener but everything is resolved up to the MonthScrollListener, which isnt available...
typealias is not visible in Java, but given the example you're talking about is:
typealias MonthScrollListener = (CalendarMonth) -> Unit
Then in Java world it should be similar to single method interface like (more about it below):
import kotlin.Unit;
interface MonthScrollListener {
Unit whatever(CalendarMonth cm);
}
It could be void because this is what Unit means in Kotlin but you know - life.
So passing Lambda in that method which expects listener should look like:
whatever.setMonthScrollListener((CalendarMonth cm) -> {
// w00t
return kotlin.Unit.INSTANCE;
});
I've basically ended up writing the same approach as suggested by #MishaAkopov
Edit (after reading about it):
But what type is it actually? It appears that Kotlin standard library has a bunch of interfaces like Function0<R> and Function2<P1,P2,R> that have one method invoke. So if you'd need to use above Kotlin code in previous Java versions it would instead look like:
Function1<CalendarMonth, Unit> listener = new Function1<CalendarMonth, Unit>() {
#Override
public Unit invoke(CalendarMonth cm) {
// Do something with calendar month
return kotlin.Unit.INSTANCE;
}
}
whatever.setMonthScrollListener(listener);
Related
I have a Kotlin library that I'm attempting to call from Java. I haven't worked with Kotlin before.
The Kotlin library function is as follows:
suspend fun decode(jwt: String): UsefulThing {
// does a bunch of stuff, removed for brevity.
return otherthing.getUsefulThing(jwt)
}
How can I call this from Java? So far I've tried:
Continuation<UsefulThing> continuation = new Continuation<>() {
#NotNull
#Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
#Override
public void resumeWith(#NotNull Object o) {
System.out.println("Result of decode is " + o);
}
};
// Call decode with the parameter and continuation.
Object result = UsefulThingKt.decode(JWT, continuation);
// result is COROUTINE_SUSPENDED
I never see any console output. Looks like the continuation is never called, or it's run in another context. I've pored over other answers and coroutines seem to have gone through a number of iterations - I can't find an explanation that really makes sense to me.
I should note that I'm running on Java 11.
How can I simply call the kotlin function?
I suggest to not even try. Suspend functions were never meant for Java interop.
Instead, convert it on the Kotlin side to something that Java understands - to CompletableFuture:
fun decodeAsync(jwt: String): CompletableFuture<UsefulThing> = GlobalScope.future { decode(jwt) }
We can freely mix Java and Kotlin code in a single module, so you can create such wrapper inside your project.
Depending on your case you could use GlobalScope (in Java we don't have structured concurrency) or you could create a custom CoroutineScope and handle its lifecycle manually.
I've imported a library into my code that uses Sealed Classes as Error Handling. The Library is written in Kotlin, and my code is in Java. Other than this line, things have gone okay.
Code Example of what I've tried to even hold the Resource:
String dogID = "1234";
DogClient dogClient = new dogClient(); //params not important.
Resource<DogDto> dogDtoResource = dogClient.fetchDog(dogID); //Problem Statement
The dogClient.fetchDog(String id) method uses a sealed class called Resource where it uses data classes to handle errors. When I try to do the above, it says it cannot access Kotlin.coroutines.Continuation.
Resource in T code:
sealed class Resource<in T> {
data class Success<T>(val data: T) : Resource<T>()
data class Error(val exception: Throwable, val statusCode: Int?) : Resource<Any>()
}
I need to access the data on Success, and know when it throws an Error. The code in Kotlin would work something like this:
when(dogClient.fetchDog(dogId)) {
is Resource.Success -> result.data;
is Resource.Error -> throw new Exception();
I am completely lost on how to translate this to Java and haven't found any articles/documentation to help me.
it says it cannot access Kotlin.coroutines.Continuation
The problem is probably not the Resource sealed class then, but rather the fetchDog function you're trying to call is most likely a suspend function in Kotlin (using Kotlin coroutines).
You can check this other answer for this specific problem. It basically boils down to providing a non-suspend function from the Kotlin code, which you will be able to call from Java.
If you cannot modify the library, you can add a simple Kotlin file to your project to write this "bridge" function (but this means you'll need to setup Kotlin compilation in your project).
I am re writing a library originally written in C# into Java and am trying my best to follow it as closely as possible. This, however, has me stumped.
This is the C# method I want to recreate in Java
public T With<TV>(Func<T, IEditable> func, TV value)
{
var pageElement = func(TypedThis);
pageActions.Add(new WebDriverValuePageAction<TV>(pageElement, value));
return TypedThis;
}
This is a generic method which is used as part of a Selenium Page Object framework where T is a BasePage and the Method takes any page element inheriting the IEditable interface.
What is stumping me is the With<TV> part of the method and how to recreate this in Java. Everything else is pretty much done. I have been able to recreate T but cannot work out how to also pass in TV (essentially a generic value) along with the function.
Direct equivalent will be
public <TV> T With(Function<T, IEditable> func, TV value)
{
IEditable pageElement = func.apply(TypedThis);
pageActions.Add(new WebDriverValuePageAction<TV>(pageElement, value));
return TypedThis;
}
I'm customizing a PLM Windchill Workflow, which provides a mechanism to execute java code snippets. Unfortunately, they are 'inserted' into prepared service's method, which means that there is no way to import classes, so I have to include full package names to use it. Don't try to understand the snippet below, just look how does it looks like:
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
while (activities.hasMoreElements()) {
wt.workflow.work.WfAssignedActivity activity = (wt.workflow.work.WfAssignedActivity) activities.nextElement();
if(activity.getDisplayIdentifier().toString().equals("Analyze Image Request")){
java.util.List<wt.workflow.work.WorkItem> workItems = wt.workflow.status.WfWorkflowStatusHelper.service.getWorkItems(activity);
for (wt.workflow.work.WorkItem workItem : workItems){
String action = workItem.getActionPerformed();
if(action != null && action.equals("Accepted")){
wt.org.WTPrincipalReference approver = workItem.getOwnership().getOwner();
n_approver = approver.getFullName() + " ("+approver.getDisplayName()+")";
wt.fc.collections.WTHashSet approverSet = new wt.fc.collections.WTHashSet(java.util.Arrays.asList(approver));
wt.project.Role role = wt.project.Role.toRole("APPROVER");
com.ptc.windchill.pdmlink.change.server.impl.WorkflowProcessHelper.setChangeItemParticipants(report, role, approverSet);
break;
}
}
break;
}
}
And my question is - how to make this code any more readable? Of course there is no way to import classes inside the method, there is even no way to divide this snippet into separate methods (as it is 'pasted' into one) so I'm looking for other ideas.
One option to make the code more readable would be to separate chained method/property calls across multiple lines.
For example, this line:
wt.project.Role role = wt.project.Role.toRole("APPROVER");
could be rewritten as:
wt.project.Role role = wt
.project
.Role
.toRole("APPROVER");
You can call this complete code from a Customized Java class.
You just have to call your class and take the final parameters required from the Java class to make it more readable.
If you need multiple outputs write multiple methods in Java class and call them in workflow expression.
You can't.
Workflows expressions are methods bodies.
A statement like
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
ends in a class under $WT_HOME/codebase/wt/workflow/expr/
with a method :
public static Object executemethod_1(Object[] var0, Object[] var1) throws Exception {
wt.fc.QueryResult activities = wt.fc.PersistenceHelper.manager.find((wt.pds.StatementSpec) activitiesQuery);
// some generated code to handle variables...
}
So, you can't use import.
However :
If you have a PDMLink version greater than 10,
You can externalize workflow expression
http://support.ptc.com/cs/help/windchill_hc/wc100_hc/index.jspx?id=WFTemplateExtExpression&action=show
This create a java class under /codebase/ext/wt/workflow/externalize
Then you can do what you want, but you'll have to compile these classes, and do a stop/start in case of modifications.
Basically, it's nothing more than calling external code from the expression, so I don't use it a lot...
I have to develop an "generic" wigdet for a GWT/GXT project and to do so I need to create an instance of an object which type is unknown. I found an approach that works perfectly in dev mode but as soon as I try to compile my project and deploy it I get an Only class literals may be used as arguments to GWT.create() error.
Here is a sample of what I do:
public class GenericEditableGrid<M> extends Grid<M>{
private final ToolBar toolBar = new ToolBar();
private final TextButton newItemButton = new TextButton();
protected GridInlineEditing<M> editing;
private final Class<M> clazzM;
public GenericEditableGrid(Class<M> parametrizedClass, String gridTitle, ListStore<M> listStore, ColumnModel<M> cm) {
super(listStore, cm);
clazzM = parametrizedClass;
// ... then I create my widget
bind();
}
private void bind(){
newItemButton.addSelectHandler(new SelectEvent.SelectHandler() {
#Override
public void onSelect(SelectEvent selectEvent) {
editing.cancelEditing();
// it is the folliwing line which is the problem obviously
M element = GWT.create(clazzM);
getStore().add(0, element);
int index = 0;
editing.startEditing(new Grid.GridCell(getStore().indexOf(element), index));
}
});
}
}
And this is how I use it in my subclasses:
super(InternationalString.class, gridTitle, new ListStore<InternationalString>(isprops.key()), buildColumnModel());
Basically, I would like to know what the problem is exactly with this approach and eventually how I should do to make it well.
Please note that my concern is not just to make it work, but more to do it the right way. As I could just avoid the problem using an abstract method which would handle the GWT.create() method in the daughter classes. But this is not the design I want, it just doesn't look right.
What I don't get also is what's the difference between doing this:
MyClass e = GWT.create(MyClass.class);
and:
Class<MyClass> clazz=MyClass.class;
MyClass e = GWT.create(clazz);
Because as far as I am concerned I think this is basically what I am doing and it looks like the same thing. Isn't it?
There's a well-worded explanation in this forum:
As the error message indicates, only class literals may be passed to the GWT.create method. The reason for this is that all GWT.create calls are basically turned into constructors at compile time, using the deferred binding rules for your module. As a result, all classes must be decided at compile time - your code requires that the at runtime the class is decided. This is too late, and so cannot be compiled.
GWT is not proper java, and so cannot be always treated as java. This is one such example of things that cannot be done in gwt. ...
What is it you are trying to do? Either you are making it far more complicated than it needs to be, or you need to write a generator to do it instead of taking this approach.