Modifying final static variable within final public class Java - java

I have a quick question regarding modifying a final public class. Based on some researches, it seems like final public class cannot be inherited or implemented. My goal is to change one final static variable within this final public class.
class name is: public final class Utils
private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
"authorization", "connection", "cookie", "content-length",
"date", "expect", "from", "host", "origin", "proxy-authorization",
"referer", "user-agent", "upgrade", "via", "warning");
I want to get rid of authorization field from this DISALLOWED_HEADERS_SET. Is there any ways to doing this?
I heard reflection is one way to modify classes. This is a Apress/java-9-revealed to a github that seems to reveal what's inside of the class
This thread (question) has been identified as XY problem. I will try to explain with more information on why I want a solution for the above problem. Before digging into the reason that drove me to ask this question, I will cover the current situation of where this problem is at as of now.
It is important to understand that this problem has been already posed by Clevertap to Oracle. If you follow Oracle link, you can see that this problem has been acknowledged and updated to Jdk 11. Hopefully, Oracle applies this fixed source code to the coming Java 10, but it is highly unlikely given the fact that Jdk 9 represents Java 9. This being said, only solution there is to use reflection which the open thread in clevertap suggests.
Now, I will briefly explain what I have achieved and am trying to figure out. I have been working on a framework that I have been developing for sending Push Notification to APNs using Java language. Everything works except one functionality.
[I will share this framework through GitHub in the near future for those trying to send notification to APNs without depending on third party frameworks, such as Jetty, Netty, or okhttp.]
The problem rises when I try to use token as a way of authentication to send notification. I have successfully created token following through the instruction provided by Apple. All I have to do is to set request header with authorization key and bearer <token> value. However, when I use .setHeader derived from jdk9.incubator.httpclient module to set these values, it automatically omits this field. As aforementioned, authorization is part of DISALLOWED_HEADERS_SET and it is clearly not allowed. If a user attempts to set "authorization" as a key value for the request header field, it is deleted. If you have any suggestions to work around this problem. It will be awesome and helpful for others facing the same problem.
Bad news folks... jdk 9.0.4 removed setSystemHeader method, so if you want to use reflection, you need to use Jdk 9.0.1
As promised before, I created java library for sending notification using pure java code and pushed it to the github. I used older version that was based on jdk10 for my published app. Older version only supported tls connection. Now the current version based on jdk11 is supporting both tls and token based authentication for sending push notification to APNs.

Will just removing that value from the set work for you? Something like this:
Field f = Utils.class.getDeclaredField("DISALLOWED_HEADERS_SET");
f.setAccessible(true);
#SuppressWarnings("unchecked")
Set<String> headers = (Set<String>)f.get(null);
headers.remove("authorization");

There is no clear for me what are you going achieve by inheritance since this value is static.
But if you possible to recompile your application, have you considered of object composition? This can be an alternate to inheritance and is often used to simulate polymorphic behavior in case of final class or 'multiply' inheritance.
If you can 'inject' the new class instead of original one (which is final), you can compose a new class that contains instance of final class and delegates its methods to them. There is no need to create same final static variable.

If you wish to bank upon reflection, this might help -
Class reqClz = request.getClass();
Method setHeaderMethod = reqClz.getDeclaredMethod("setSystemHeader", String.class, String.class);
setHeaderMethod.setAccessible(true);
setHeaderMethod.invoke(request, "authorization", "<token>");
for which you might have to open the incubator module's package with the use of VM arg:-
--add-opens jdk.incubator.httpclient/jdk.incubator.http=<your-package x.y.z>
OR
Was also thinking that, another way here possibly could be patch the module content
--patch-module <module>=<file>(<pathsep><file>)*
for the jdk.incubator.http.internal.common.Utils class but as recommended not more than testing or debugging purpose.

The following code allows you to change the value of private static fields (non-final):
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class SetFinalField {
#SuppressWarnings("unchecked")
public final static void main(String[] args) throws Exception {
System.out.println("elements before: " + SetTarget.DISALLOWED_HEADERS_SET);
Field f = SetTarget.class.getDeclaredField("DISALLOWED_HEADERS_SET");
f.setAccessible(true);
ArrayList<String> l = new ArrayList<String>();
l.addAll((Set<String>) f.get(null));
l.remove("authorization");
HashSet<String> hs = new HashSet<>();
hs.addAll(l);
f.set(null, Collections.unmodifiableSet(hs));
System.out.println("elements after: " + SetTarget.DISALLOWED_HEADERS_SET);
}
public final static class SetTarget {
private static Set<String> DISALLOWED_HEADERS_SET;
static {
HashSet<String> l = new HashSet<>();
Collections.addAll(l, new String[]{"authorization", "connection", "cookie", "content-length",
"date", "expect", "from", "host", "origin", "proxy-authorization",
"referer", "user-agent", "upgrade", "via", "warning"});
DISALLOWED_HEADERS_SET = Collections.unmodifiableSet(l);
}
}
}
If you change the field to final this will be prevented, so to answer your question: It's not possible to do what you currently try to do using reflection. There is a way, though by using JNI, but you don't want to go that way. Whatever you try to accomplish you should try to find a different solution, e.g. by checking the class that is using this header if it can be configured with an alternate set of disallowed header values or go the way #nullpointer described.

Related

Minecraft RegistryObject not present

I'm a new minecraft modder, and I'm trying to make a new mob bucket item.
Everytime I run the game, the game crashes saying that the RegistryObject for my modded entity isn't present.
Here is the code in question:
public class ItemInit {
private ItemInit() {}
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, TheDeepBlue.MODID);
public static final RegistryObject<MobBucketItem> EEL_BUCKET =
ITEMS.register("eel_bucket", () -> new MobBucketItem(EntityInit.EEL.get(), Fluids.WATER, SoundEvents.BUCKET_EMPTY_FISH, new Item.Properties().stacksTo(1).tab(CreativeModeTab.TAB_MISC)));
}
I would really appreciate some help on this. Please let me know if I need to provide anything else. Thank you.
Your entity will load after your item. So EntityInit.EEL is not loaded. You should not use RegistryObject for your entity, but you can directly instantiate it instead.
For example:
public static final EntityType<Entity> FOO = EntityType.Builder.of(...)
Before beginning, it would be beneficial to those wishing to assist you if you were to mention the version of Forge that you are targeting. That said, as it appears you are using DeferredRegistry and RegistryObject to register your entities, etc, I believe that the following information will be correct for your version.
The problem that is occurring, is that the deferred registration is attempting to eagerly construct MobBucketItem when it is time to register your bucket item. As Items are registered before Entities, this leads to the RegistryObject for EntityInit.EEL being empty, hence calling get() crashing the mod loading process.
The solution is to use the MobBucketItem's other constructor, which takes a supplier to the entity as its first argument and not an EntityType. A Supplier is either a class that implements the supplier interface, or a lambda that returns a value of the form () -> value. This will look familiar as that is how you provide the value to return to the registry once Forge begins building the Item Registry
public static final RegistryObject<MobBucketItem> EEL_BUCKET =
ITEMS.register("eel_bucket", () -> new MobBucketItem(() -> EntityInit.EEL.get(), () -> Fluids.WATER, ()-> SoundEvents.BUCKET_EMPTY_FISH, new Item.Properties().stacksTo(1).tab(CreativeModeTab.TAB_MISC)));
Internally, Forge deprecates the constructor you were using to make the MobBucketItem and wraps the first 3 arguments in suppliers, then calls the form of the constructor which accepts those suppliers. This is specifically to allow the use of modded entities, fluids, and sounds, even if their registries haven't been built yet.
So to wrap up, take the first three arguments you were previously passing into the constructor, and turn them into suppliers. If that version of the constructor does not exist in the version of Forge you are targeting, then I recommend updating your version of Forge to one that does provide that overload.

Serving static page from custom scala action in Play Framework

I'm new to scala, but have some experience using the play framework in Java. I've added the SecureSocial authentication library, which defines a SecuredACtion, and it seems to be working correctly. However, I'm having trouble understanding the expected content within the custom action in scala code.
Here's my controllers class. Ideally, "index" would simply redirect the authenticated request to "unprotectedIndex" somehow, but that doesn't seem to be possible. So if not, next best thing is simply to serve the file directly from inside of the secured action, but that's also not working.
What is missing from my code?
object Application extends Controller with securesocial.core.SecureSocial {
// this doesn't compile, but it's a long scala exception that I don't know how to fix.
def index = SecuredAction { implicit request =>
Assets.at("/public", "index.html").apply(request)
}
def unprotectedIndex = Assets.at("/public", "index.html")
}
It seems like it's expecting a SimpleResult but getting a Future[SimpleResult] - this feels like it shouldn't be complicated, but what am I missing?
It seems like you are using play framework 2.2. There were some changes and most methods return Future[SimpleResult] instead of just Result or SimpleResult. You can check if you are able to do like this: def index = SecuredAction.async {...} (but I'm almost sure you can't).
You can use this approach to make it work correctly:
import scala.concurrent.Await
import scala.concurrent.duration._
def index = SecuredAction { implicit request =>
Await.result(Assets.at("/public", "index.html").apply(request), 5 seconds) //you can specify you maximum wait time here
}
EDIT
Even one more thing to simplify:
Await.result(unprotectedIndex(request), 5 seconds)
So you can call your unprotectedIndex from your index Action
So, just by looking at syntax highlighting in my IDE I have been able to get something that seems to compile and work but looks deeply wrong to me.
I changed it to this:
def index = SecuredAction { implicit request =>
Assets.at("/public", "index.html").apply(request).value.get.get
}
Is that the correct way to do this? It looks really weird to me, am I just not familiar with the idioms?

Append type level validation error message to specific field

I've got a simple class which get's validated using the boolean isValid() method, which works and of course the error message is at class/type level.
Here's my simple class:
public class NewPasswordDTO {
#NotNull
public String password;
#NotNull
public String confirmation;
#AssertTrue(message="Passwords must match.")
protected boolean isValid() {
return password.equals(confirmation);
}
}
But what I really want is something like that:
public class NewPasswordDTO {
#NotNull
#Equals("confirmation", message="...")
public String password;
#NotNull
public String confirmation;
}
So the error message would be set at field level and not at class/type level.
Is this possible somehow? Maybe using a custom Validator for that class?
Thanks in advance!
SOLUTION:
Thanks to Gunnar! I've just came up with a nice, universal solution :-). I simply used (means copy & paste) the code from Hibernates #ScriptAssert and ScriptAssertValidator and modified it slightly:
#ScriptAssert:
Add new String field(). (this is where the error message gets appended)
ScriptAssertValidator:
Inside the initialize method, make sure to also save the fieldName and message properties, because we need to access them in the next step
Add this snippet at the bottom of isValid method:
context.buildConstraintViolationWithTemplate(errorMessage)
.addPropertyNode(fieldName).addConstraintViolation();
Also add context.disableDefaultConstraintViolation(); somewhere inside the isValid method to not generate the default error message which else would get appended at class level.
And that's it. Now I can use it like that:
#FieldScriptAssert(lang="javascript", script="_this.password.equals(_this.confirmation)", field="password", message="...")
public class NewPasswordDTO { ... }
You either could use the #ScriptAssert constraint on the class (note that a constraint should always be side-effect free, so it's not a good idea to alter the state of the validated bean; instead you should just check whether the two fieldss match) or you implement a custom class-level constraint.
The latter also allows to point to a custom property path for the constraint violation, which it allows to mark the "confirmation" property as erroneous instead of the complete class.
Simple answer : It is not (unless you implement it) :http://docs.oracle.com/javaee/6/api/javax/validation/constraints/package-summary.html shows all annotation constraints.
Of course you could inject your string as a resource in your class by #producer and so on (which recently is discussed to be removed in jdk8), but you could not use this value for your assert. In reply to the comment:
This was asuming that the nature is a constant string which you would like to use as a string resource.And then of course it is possible to write your own class based on java.lang.string with a #Producer which is then #Inject - able. Though it is certainly not the way I personally would deal with constant strings.
If you’re using the Spring Framework, then as an alternative to the #ScriptAssert using a JSR 223 scripting, you can use the #SpELAssert that uses the Spring Expression Language (SpEL). The advantage is that it doesn’t need any JSR 223 compliant scripting engine which may not be available on some environments. See this answer for more information.

Enterprise Architect - MDA converst Map to List

I am using EA for creation of PIM. When I generate java code directly I am getting correct data type where I want - Map where I set qualifiers on association properties which as I understand meas that it is going to be a map. And that works as expected. Hovewer when I do the MDA transformation and generete code - properties are conveted to List (which is bad) bug setters and getters method keep using Map as in the following example:
public class Check {
private List< Comp> comps;
private List< Gratuity> gratuities;
public Check(){
}
public Map<String, Comp> getcomps(){
return comps;
}
public Map<String, Gratuity> getgratuities(){
return gratuities;
}
I am using default transformation package for Java. I tried to add following line to Java transformation for connector is source section
%connectorType%
%PI="\n "%
{
%TRANSFORM_CURRENT()%
%TRANSFORM_REFERENCE("Connector",connectorGUID)%
Source
{
%TRANSFORM_REFERENCE("Class",connectorSourceElemGUID)%
access=%qt%%connectorSourceAccess == "Public" ? "Private" : value%%qt%
qualifier=%connectorSourceQualifier%
%TRANSFORM_CURRENT("Source","access")%
}
Target
{
%TRANSFORM_REFERENCE("Class",connectorDestElemGUID)%
access=%qt%%connectorDestAccess == "Public" ? "Private" : value%%qt%
%TRANSFORM_CURRENT("Target","access")%
%PI="\n"%
}
}
but that doesn't seem to help
This is an incomplete answer, but it's too long to go in a comment.
I'm not convinced that the connector source qualifier determines which collection class (Map, List) is used. There are three things involved here: the MDA transform template, the code generation template and the collection class options.
Check Tools -- Options -- Source Code Engineering -- Java. There you'll find settings for Default Collection Class and Additional Collection Classes (these are used for attributes), and (by clicking the Collection Classes button) collection class settings for associations. Check these.
Also, check the Linked Attribute Declaration template for Java code generation. It seems to me that this does not check the qualifier, but it does check %linkAttCollectionClass%.
I got a reply form Enterprise Architect support which says it is bug - original message:
I am sorry it does not work because there's an issue with regard to transformation of the Connector 'qualifier'.
The transformation template '%TRANSFORM_CURRENT()%' (and your new added 'qualifier="tr: String') is all correct, but the issue makes it fail to transform that qualifier value across.
We are going to resolve this issue in a future release of EA. Unfortunately I cannot provide a timeframe for release.
Issue ID: 13106266

timeout is not being taken into consideration using axis1.4

I'm setting the timeout when initializing the webservice stub and I'm even logging it using getTimeout() before making the call to make sure it's set but the call completes regardless of the timeout value set. Is it possible this is a bug or am I missing something here?
Below is my code doing this:
proxy = new DCPControllerWSPortTypeProxy();
proxy.setEndpoint(endpoint);
((Stub)proxy.getDCPControllerWSPortType()).setTimeout(120000);
To fix the problem, you will have to add the following class wherever you want in your project. When I had a similar problem, I have declared it as a private class in the same class where I'm instantiating my stub. (I'm currently using Axis 2 )
private class CustomNetworkClient extends sun.net.NetworkClient
{
public CustomNetworkClient(int readTimeout)
{
defaultSoTimeout = readTimeout;
}
}
After doing that, you could add the following line in your code, which will set the timeout.
CustomNetworkClient client = new CustomNetworkClient(SOAP_READ_TIMEOUT);
Or you could simply do the following, since you don't really need the object that's being created:
new CustomNetworkClient(SOAP_READ_TIMEOUT)
This has been reported as a bug before, where connection timeouts and read timeouts are not being set when using HTTPS connections : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4700777
The following link helped me figure out this workaround:
http://www.noizeramp.com/article.php?article=se-networking_specifics_under_Java_Web_Start
I hope this will help you somehow =)

Categories

Resources