java.lang.IllegalAccessException: is related to public / private attribute for classes? - java

I get the following error in my Java code:
java.lang.IllegalAccessException: Class org.apache.commons.digester.ObjectCreateRule can not access a member of class Response with modifiers ""
Is it maybe because class Response is not public class ?
If so, how can I make it accessible and keep the class Response in the same file with the main class ?
thanks
Update, Code: http://www.smipple.net/snippet/aneuryzma/on:%20is%20related%20to%20public%20/%20private%20attribute%20for%20classes%20%3F

As far as I remember your class Response should follow the bean convention: should be public, should have public default constructor and should have setters and getters for all fields that you refer from your xml.

Yes it is, as IllegalAccessException documentation says.
You can circumvent access modifiers with reflection. For example, to access private fields, use Class.getDeclaredField(String) to get a specific Field (works also for private fields - using plain getField can only get public members), and then set Field.setAccessible(true). Now the field can be used as if it was public.
You can also circumvent access modifier with JNI. It doesn't care about access modifiers at all. Yet one more way is to generate custom bytecode with a tool such as ASM.

can not access a member of class Response with modifiers ""
A member is an instance variable, modifiers are public, protected, static, ...
So it looks to me, that the Response class has a field that can't be accessed or created through the apache-commons-digesters ObjectCreationRule.
Either you have a Response class that is not compatible with digester or the error lies within the xml file that defines the Response class.
Looking at your code - the only Java "items" with no access modifiers are the classes Response and Request. Maybe the error tells us that those classes have to be public.

ObjectCreateRule attempts uses the loads Request via it's class name and then invokes Class.newInstance(). For this to work the Request and Response both need public and have public default constructors.
You have two options for this:
1. Place Request and Response in their own source files and make them public
2. Nest Request and Response inside your public top level class and make them public static.
If you took option two then your code would look like this:
import java.io.Reader;
import java.io.StringReader;
import org.apache.commons.digester.Digester;
public class DigExample {
public static void main(String ar[]) {
try {
Digester digester = new Digester();
digester.setValidating( false );
digester.addObjectCreate( "response", Response.class );
digester.addObjectCreate( "response/request", Request.class );
digester.addBeanPropertySetter("response/request/name", "name" );
digester.addBeanPropertySetter("response/request/value", "value" );
digester.addSetNext( "response/request", "setRequest" );
digester.addBeanPropertySetter( "response/matches", "matches" );
Reader reader = new StringReader(
"<?xml version='1.0' encoding='UTF-8'?>" +
"<response>" +
"<request><name>books</name><value>xml</value></request>" +
"<matches>20</matches>" +
"</response>");
Response response = (Response)digester.parse( reader );
System.out.println( response.toString() );
} catch( Exception exc ) {
exc.printStackTrace();
}
}
static public class Response {
public Response(){}
private int _matches = 0;
private Request _request;
public Request getRequest() {
return _request;
}
public void setRequest(Request request) {
_request = request;
}
public int getMatches() {
return _matches;
}
public void setMatches(int matches) {
_matches = matches;
}
}
static public class Request {
public Request() {}
private String _name = "";
private String _value = "";
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
public String getValue() {
return _value;
}
public void setValue(String value) {
_value = value;
}
}
}
As other people have mentioned, if you were using reflection directly yourself you could probably circumvent the access modifiers, but this isn't an option in your example.

Related

How to automatically register new subclasses?

I'm working on the reporting module of our web-application. There are six reports available to the client, each of them has a code. The problem is that now the module is not closed for modification with respect to potential addition of new reports, thus violating OCP.
To elucidate, I have the following set of classes:
A generic report class, which all other reports inherit:
public abstract class Report
{
private final String code;
Report(String code)
{
this.code = code;
}
public String getCode() { return code; }
public abstract byte[] generate();
}
A servlet which manages POST requests for report generation:
public class ReportServlet extends HttpServlet
{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
Report requested = ReportRegistry.lookup(req.getParameter("report_code"));
byte[] bytes = requested.generate();
// attach bytes to response
}
}
Report registry, which stores all existing reports for later access:
public class ReportRegistry
{
private static final Map<String, Report> registry = new HashMap<>();
static
{
// Violates OCP!
registerReport( GlobalReport.getInstance() );
registerReport( AvailablePackagesReport.getInstance() );
registerReport( BadgeReport.getInstance() );
registerReport( PlacementReport.getInstance() );
registerReport( TerminalReport.getInstance() );
registerReport( VerActReport.getInstance() );
}
private ReportRegistry() { }
static void registerReport(final Report report)
{
registry.put(report.getCode(), report);
}
public static Report lookup(final String reportCode)
{
return registry.get(reportCode);
}
}
However, ReportRegistry violates OCP, since we need to add an entry to its static block every time a new report is created.
My question is: how can I make any new subclass of Report to be registered automatically, without any explicit mentioning?
I would think OCP would be more applicable to Report itself, and that having ReportRegistry sitting outside of the class hierarchy would be a valid design.
That said, if you want to avoid modifying ReportRegistry each time you create a Report subclass, you could use some reflection tricks to seek out all such subclasses, or create an annotation that ReportRegistry could search for to register all classes with instances.
You should look at https://github.com/ronmamo/reflections. I have never tried this library but it looks like it does what you want (retrieving all subclasses of a known class).
You could then register them in your ReportRegistry static block.

In JavaBean, what calls setter method?

I'm struggling with how the getter/setter methods are called in a Java Bean. I don't see examples of the tutorials (https://netbeans.org/kb/docs/web/jsf20-intro.html) calling the setter methods and yet the values are obviously set.
As a result, I'm having trouble making sure my setter methods are being called. For instance...
#Named(value = "someJavaBean")
#SessionScoped
public class someJavaBeanSerializable {
String webServiceResponse;
public void setWebServiceResponse() {
this.webServiceResponse = "Just a test";
}
public String getWebServiceResponse() {
this.setWebServiceResponse();
return this.webServiceResponse;
}
public someJavaBean() {
System.out.println("You are in someJavaBean");
}
}
It appears that I have to manually call setWebSErviceResponse() in order for the setter to run which is typical of other languages. I'm okay doing that, but based on what I've read, I'm not sure that is the correct way to do it.
Any help or clarification would be appreciated.
Thank you,
Java beans define behavior by convention:
A class has a default public constructor with no arguments to it (or, essentially, no constructor).
Class properties are accessed using the convention of getters and setters - namely getWebServiceResponse() and setWebServiceResponse(String response).
The only methods present in the bean are the methods to interact with the fields - that is, a setter and getter for each field. If you have a final field, then this would change (you would only be able to have a getter).
Not having a parameter in your setter violates this convention.
Also, it's bad style to call your setter inside of your getter - the idea behind a setter is that it only sets a field, and a getter only returns whatever value is inside of that field - even if it's null. I'd remove the call to your setter as well.
Lastly, public someJavaBean() is invalid - you may have meant to return void.
Your setter method needs a parameter:
public void setWebServiceResponse(String webServiceResponse) {
this.webServiceResponse = webServiceResponse;
}
Sorry to be dense. In the following code from the tutorial (https://netbeans.org/kb/docs/web/jsf20-intro.html), where is the setter called?
#ManagedBean (name="UserNumberBean")
#SessionScoped
public class UserNumberBean implements Serializable{
Integer randomInt;
Integer userNumber;
String response;
public String getResponse() {
if ((userNumber != null) && (userNumber.compareTo(randomInt) == 0)) {
//invalidate user session
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
session.invalidate();
return "Yay! You got it!";
} else {
return "<p>Sorry, " + userNumber + " isn't it.</p>"
+ "<p>Guess again...</p>";
}
}
public Integer getUserNumber() {
return userNumber;
}
public void setUserNumber(Integer userNumber) {
this.userNumber = userNumber;
}
/**
* Creates a new instance of UserNumberBean
*/
public UserNumberBean() {
Random randomGR = new Random();
randomInt = new Integer(randomGR.nextInt(10));
System.out.println("Duke's number : " + randomInt);
}
}

JSON Jackson parse different keys into same field

I have a POJO which has a field:
public class Media {
private Asset asset;
}
Everything works perfectly when parsing a json response into this asset POJO. but however there is a slight difference with the key this asset comes with. It can either be:
#JsonProperty("cover_asset")
or
#JsonProperty("asset")
Is there a way to annotate the POJO to recognize this case and de-serialize into the same field. Its not possible for both of them to appear in the same response.
Well, as only deserialization is your concern, #JsonAlias introduced in 2.9 is perfect for this situation. You can do something like this:
#JsonAlias({"cover_asset", "asset"})
private Asset asset;
#JsonAlias docs:
Annotation that can be used to define one or more alternative names
for a property, accepted during deserialization as alternative to the
official name. Alias information is also exposed during POJO
introspection, but has no effect during serialization where primary
name is always used.
Note: Make sure you update all related dependencies(annotations, core, databind) if you are using them. Updating just annotations without others threw me runtime error.
More succinctly, I would suggest using two separate #JsonSetter annotations for this. Here's a working example. This means that your java class will only have one getter method to use for the property instead of two. You can also make the setter you don't want exposed to clients of Media private and treat one of the json keys in a special manner.
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.ObjectMapper;
#SuppressWarnings("unused")
public class Media {
private Asset asset;
#JsonGetter("asset")
public Asset getAsset() {
return asset;
}
#JsonSetter("asset")
public void setAsset(Asset asset) {
this.asset = asset;
}
#JsonSetter("cover_asset")
private void setMediaAsset(Asset asset) {
if (this.asset == null) {
setAsset(asset);
}
}
private static class Asset {
#JsonProperty("foo")
private String foo;
}
public static void main(String[] args) throws Exception {
String withAsset = "{'asset': {'foo':'bar'}}";
String withCoverAsset = "{'cover_asset': {'foo':'bar'}}";
ObjectMapper mapper = new ObjectMapper();
Media mediaFromAsset = mapper.readValue(withAsset.replace('\'','"'), Media.class);
Media mediaFromCoverAsset = mapper.readValue(withCoverAsset.replace('\'','"'), Media.class);
System.out.println(mediaFromAsset.asset.foo.equals(mediaFromCoverAsset.asset.foo));
}
}
Great answer By Vikas with JsonAlias.
Just adding that you can also benefit from both of the worlds (JsonProperty&Alias) [Since jackson 2.9]:
#JsonProperty("cover_asset")
#JsonAlias({"asset", "cover_asset","amazing_asset"})
private Asset asset;
Reference.
I'd propose to use getters/setters, for both property names, which are referring to the same POJO field.
public class Media {
private Asset asset;
#JsonProperty("cover_asset")
public Asset getCoverAsset() {
return asset;
}
public void setCoverAsset(Asset asset) {
this.asset= asset;
}
#JsonProperty("asset")
public Asset getAsset() {
return asset;
}
public void setAsset(Asset asset) {
this.asset= asset;
}
}
See also my answer to possible duplicate question:
Different names of JSON property during serialization and deserialization

Does Restlet support parsing URLs into calling methods with parameters?

Take the following example.
I have a resource
public class HelloWorldResource extends ServerResource {
#Get
public String represent(String arg) {
return "hello, world (from the cloud!)" + arg;
}
}
That is mapped by
router.attach("/hi/{message}", HelloWorldResource.class);
Is it possible to configure the routing such that accessing /hi/somestuffhere will make restlet fill in the arg parameter in the represent method?
Try this:
String msg = (String) getRequest().getAttributes().get("message");
You can place this in an overriden doInit() method in order to let this happen automatically for all your requests to this resource.

Accessing private static methods from a public static context

Consider this sample class,
class TargetClass {
private static String SENSITIVE_DATA = "sw0rdfish";
private static String getSensitiveData() {
return SENSITIVE_DATA;
}
}
When I do this,
import java.lang.reflect.Method;
public class ClassPiercing {
public static void main(String... args) throws Exception {
Class targetClass = Class.forName("TargetClass");
Method[] methods = targetClass.getDeclaredMethods();
methods[0].setAccessible(true);
String sensitiveData = (String)methods[0].invoke(null, null);
System.out.println("Sensitive Data: " + sensitiveData);
}
}
The output is,
Sensitive Data: sw0rdfish
This is dangerous. How do I prevent this from happening?
Well, use a SecurityManager.
http://java.sun.com/javase/6/docs/api/java/lang/SecurityManager.html
http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html#ReflectPermission
disabling ReflectPermission should do the trick.
The point of access control is not to prevent someone from hacking in to your code; It's a matter of signalling intend to other programmers (eg. api design). If you don't trust the other program, you should run use different measures. For example, you could encrypt the data somehow.

Categories