I'm trying in my code to use the following expression
Map<String, String> headersMap =
Collections.list(request.getHeaderNames())
.stream()
.collect(Collectors.toMap(
name -> name,
request::getHeader));
as shown here
but Eclipse complains of type mismatch:
What's the correct way to accomplish this and why? Why does the one in the link not uses any casting?
UPDATES:
Considering the suggestion from #Eugene, the following monstrosity seems to make the compiler happier:
Map<String, String> headersMap = new HashMap<>();
Collections.list(request.getHeaderNames())
.forEach(x -> headersMap.put((String)x, (String)request.getHeader((String)x)));
Perhaps there are more succinct ways of expressing it in Java 8?
Contrary to the #Eugene's assertions, what makes the difference here is that org.eclipse.jetty.server.Request.getHeaderNames() produces an Enumeration<Object> which, consequently, being fed into Collections.list() results in an ArrayList<Object> which is the reason Java compiler doesn't accept it.
Casting the end result to (Map<String, String>), as suggested by an IDE alleviates the complaint:
Map<String, String> headersMap =
(Map<String, String>)
Collections.list(request.getHeaderNames())
.stream()
.collect(Collectors.toMap(
name -> name,
request::getHeader));
Apparently the pages I mentioned (here and Servlet Filter: How to get all the headers from servletRequest?) are using the original method without eventually casting it to Map<String, String> are broken to start with (as suggested by #Eugene) or work for some other obscure reason.
Perhaps someone can shed light on that mystery.
UPDATES:
Upon further investigation as prompted by #StuartMarks's comment, indeed the culprit is the version of Jetty being used. Request.getHeaderNames() is implemented differently between the two.
Version 7.6.16 (which we happened to be using) uses raw-typed Enumeration, causing the havoc:
whereas Jetty ver. 9.4.7 uses a typed Enumeration:
It explains why the article I referenced in my original question as well as the other SO mention are both correct - they simply refer to a new implementation of that method. Again, thank you to #StuartMarks for pointing it out.
Related
I am trying to call an external API from an Excel on web. However, I am stuck on trying to get the result from the fetch call. I am even using the Office doc example to make sure
From an Excel, click on Automate to create a new script
async function main(workbook: ExcelScript.Workbook): Promise<void> {
let fetchResult = await fetch('https://jsonplaceholder.typicode.com/todos/1');
let json = await fetchResult.json();
}
I keep on getting the following message (at the fetchResult.json() call)
"Office Scripts cannot infer the data type of this variable or inferring it might result in unexpected errors. Please annotate the type of the variable to avoid this error. You can also use the Quick fix option provided in the editor to auto fill the type based on the usage. Quick Fix can be accessed by right clicking on the variable name and selecting Quick Fix link."
When running the Chrome inspector, the API request seems to be on hold "CAUTION: request is not finished yet"
PS: I am not the Office administrator and is not reachable right now, but hoping this is not a problem with my user or the Office account configuration
Any idea what the problem might be?
Thanks!
"any" types not being allowed in OfficeScript is by design. We think any types in general can lead to developer errors. I understand it can be hard to declare types – but these days most popular APIs provide you the interface (or d.ts) that you can use.
Secondly, there are tools such as https://quicktype.io/typescript where you can type in your sample JSON and it’ll give you the full interface which you can then declare in your code using interface keyword.
See this code for example: https://github.com/sumurthy/officescripts-projects/blob/main/API%20Calls/APICall.ts
You don’t need to declare all properties – only the ones you’ll use.
It’s more up-front work – but in the end the quality is better.
Adding an interface definition for the expected JSON type fixed the problem for me.
interface Todo {
userId: number;
id: number;
title: string;
completed: boolean
}
async function main(workbook: ExcelScript.Workbook): Promise<void> {
let fetchResult = await fetch('https://jsonplaceholder.typicode.com/todos/1');
let json: Todo = await fetchResult.json();
console.log(json);
}
You may need to define a different interface if the Web API you're calling returns different data structure.
val args = Bundle()
args.putString("type", details.type)
navigator.navigate(context!!, findNavController(), Destination.TYPE, args)
I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...
val type: String = arguments.getString("type")
The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?
It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.
It's a matter of knowledge that is available in the receiving Fragment.
The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).
Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.
There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.
I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.
val type: String = arguments!!.getString("type")!!
The code above will crash if either:
a) arguments weren't set, or
b) String with type wasn't put in the arguments Bundle.
You are right, that is a : null ability issue.
First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else
To read the string safely you can use:
val type: String = arguments?.getString("type").orEmpty()
The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.
The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.
If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.
isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.
While decompiling .net assembly using de4dot I am getting following message in console:
Error calculating max stack value. If the method's obfuscated, set CilBody.KeepOldMaxStack or MetadataOptions.Flags (KeepOldMaxStack, global option) to ignore this error
How do I set CilBody.KeepOldMaxStack or MetadataOptions.Flags?
Maybe a bit late, but I ran into the same problem today, finding your open question while looking for a solution, and this is how I solved it - I hope it works for you, too:
// Working with an assembly definition
var ass = AssemblyDef.Load("filename.dll");
// Do whatever you want to do with dnLib here
// Create global module writer options
var options = new ModuleWriterOptions(ass.Modules[0]);
options.MetadataOptions.Flags |= MetadataFlags.KeepOldMaxStack;
// Write the new assembly using the global writer options
ass.Write("newfilename.dll", options);
If you want to set the flag only for a selection of methods that produce the problem before writing, just for example:
// Find the type in the first module, then find the method to set the flag for
ass.Modules[0]
.Types.First((type) => type.Name == nameof(TypeToFind))
.FindMethod(nameof(MethodToFind))
.KeepOldMaxStack = true;
CilBody is maybe a bit confusing, if you're not too deep into the internal .NET assembly structures: It simply means the body object of the method that produces the problem, when writing the modified assembly. Obfuscators often try to confuse disassemblers by producing invalid structures, what may cause a problem when calculating the maxstack value before writing the assembly with dnLib. By keeping the original maxstack value, you can step over those invalid method structures.
In the context of de4dot it seems to be a bug, or the application is simply not designed to solve invalid method structures of obfuscated assemblies - in this case there's no solution for you, if the de4net developer won't fix/implement it, and you don't want to write a patch using the source code from GitHub.
I was wondering how to bind values where the source of the bind could be null.
I have a property:
private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null);
I also have a text field:
#FXML
private Text txtCurrentOperation;
I would like to bind the textProperty of the field to the value of the operation object.
My first thought was to use FluentAPI with its when/then/otherwise construct, but it is eagerly evaluated so the solution:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(operation.get().getName()));
will throw a NPE, because the parameter of otherwise is evaluated no matter what the result of the when.
My next idea was to use lambda somehow:
txtCurrentOperation.textProperty().bind(() ->
new SimpleStringProperty(
operation.isNotNull().get() ? "Null" : operation.get().getName()
));
But the bind has no lambda enabled solution. (Later I realized that it couldn't have, becasue the real work goes backward: the change of the binded object (operation) will trigger the update of the binder (the field text property).)
Some articles I found suggested to use an "extremal" value for the property instead of null. But Operation is a complex and heavy weight component so it is not trivial to construct an artifical instance to represent null. Even more, this seems to me boilercode, something the binding mechanism is designed to help eliminating.
My next try was to logically swap the binding direction and add listener to the operation property and let it update the field programatically. It works and rather simple as long as the need of update only depends the operation object instances:
operation.addListener((e) -> {
txtCurrentOperation.setText(operation.isNull().get() ?
"Null" : operation.get().getName());
});
operation.set(oper);
It is relatively simple, but doesn't work: it throws "A bound value cannot be set." exception and I don't see why is the text property of the control regarded as bound.
I ran out of ideas. After much searching, I still cannot solve the simple problem to update a text field differently based on whether the source is null or not.
This seems so simple and everyday problem, that I am sure I missed the solution.
If a 3rd party library is an option, check out EasyBind. Try something like this:
EasyBind.select(operation)
.selectObject(Operation::nameProperty)
.orElse("null");
There's also a JavaFX JIRA issue for the type of functionality provided by EasyBind. If you don't want to use a 3rd party library, try Bindings.select:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(Bindings.select(operation, "name"));
Be aware the null checking in Bindings.select isn't super efficient. There's a JIRA issue for it.
Just in case if somebody using not Java itself but Kotlin.
It is a good idea to use wonderful tornadofx library.
There you can just use operation.select{it.name}. Although, this feature seems not to be documented yet, so it took some time to discover it.
Only recently, I discovered that both Java and C# do not support reflection of local variables. For example, you cannot retrieve the names of local variables at runtime.
Although clearly this is an optimisation that makes sense, I'm curious as to whether any current languages support full and complete reflection of all declarations and constructs.
EDIT: I will qualify my "names of local variables" example a bit further.
In C#, you can output the names of parameters to methods using reflection:
foreach(ParameterInfo pi in typeof(AClass).GetMethods()[0].GetParameters())
Trace.WriteLine(pi.Name);
You don't need to know the names of the parameters (or even of the method) - it's all contained in the reflection information. In a fully-reflective language, you would be able to do:
foreach(LocalVariableInfo lvi in typeof(AClass).GetMethods()[0].GetLocals())
Trace.WriteLine(lvi.Name);
The applications may be limited (many applications of reflection are), but nevertheless, I would expect a reflection-complete language to support such a construct.
EDIT: Since two people have now effectively said "there's no point in reflecting local variable names", here's a basic example of why it's useful:
void someMethod()
{
SomeObject x = SomeMethodCall();
// do lots of stuff with x
// sometime later...
if (!x.StateIsValid)
throw new SomeException(String.Format("{0} is not valid.", nameof(x));
}
Sure, I could just hardcode "x" in the string, but correct refactoring support makes that a big no-no. nameof(x) or the ability to reflect all names is a nice feature that is currently missing.
Your introductory statement about the names of local variables drew my interest.
This code will actually retrieve the name of the local var inside the lambda expression:
static void Main(string[] args)
{
int a = 5;
Expression<Func<int>> expr = (() => a);
Console.WriteLine(expr.Compile().Invoke());
Expression ex = expr;
LambdaExpression lex = ex as LambdaExpression;
MemberExpression mex = lex.Body as MemberExpression;
Console.WriteLine(mex.Member.Name);
}
Also have a look at this answer mentioning LocalVariableInfo.
Yes, there are languages where this is (at least kind of) possible. I would say that reflection in both Smalltalk and Python are pretty "complete" for any reasonable definition.
That said, getting the name of a local variable is pretty pointless - by definition to get the name of that variable, you must know its name. I wouldn't consider the lack of an operation to perform that exact task a lacuna in the reflection facility.
Your second example does not "determine the name of a local variable", it retrieves the name of all local variables, which is a different task. The equivalent code in Python would be:
for x in locals().iterkeys(): print x
eh, in order to access a local var you have to be within the stackframe/context/whatever where the local var is valid. Since it is only valid at that point in time, does it matter if it is called 't1' or 'myLittlePony'?