0

Using MongoDB, I need to persist objects from Twitter4J. Twitter4J uses interfaces, which are implemented in JSON versions. Example:

The API returns Status (an interface), and Status is implemented as StatusJSONImpl.

I can't save Status to MongoDB, I need to implement StatusJSONImpl.

My issue is, this class StatusJSONImpl is not public (see here) so I can't use it in my code. I tried to download the source of Twitter4J to manually add "public" to StatusJSONImpl: I can do:

Status status = twitter.updateStatus(latestStatus);    
String statusStringified = TwitterObjectFactory.getRawJSON(status);
StatusJSONImpl statusImplemented = (StatusJSONImpl) TwitterObjectFactory.createUserList(statusStringified);
SingletonLaunchDB.getMongo().save(statusImplemented);

But I still get a java.lang.IllegalAccessError on the class StatusJSONImpl at run time.

I see from other SA answers that users routinely point other users to this Impl classes... how do they do to use it in their code?

Your help is much appreciated.

Community
  • 1
  • 1
seinecle
  • 10,118
  • 14
  • 61
  • 120

2 Answers2

0

Status is serializable. To recover StatusJSONImpl from statusStringified you can write.

JSONObject json = new JSONObject(statusStringified);
Status status = new StatusJSONImpl(json);

The code sample is from StatusSerializationTest.java

I hope this helps.

Max Luan
  • 305
  • 3
  • 9
  • Not helpful I am sorry. The details of how I get the Status object are irrelevant, and I don't run my code from command line so I don't need the args[0] bit anyway. Yes, I could reimplement dozen of classes of Twitter4J but my question is about how could I be spared this misplaced effort - there must be a better way. – seinecle Apr 19 '16 at 07:36
  • @seinecle I updated the answer, please check it out. – Max Luan Apr 19 '16 at 07:59
  • It clarifies, thanks a lot! However, the StatusSerializationTest.java class you mention is situated inside the same package as StatusJSONImpl, which is why it can access it. My code is situated outside of Twitter4J of course, so can't access StatusJSONImpl. Is there an obvious solution to this? – seinecle Apr 19 '16 at 12:47
0

Use the static factory method on TwitterObjectFactory:

Status status = TwitterObjectFactory.createStatus(statusAsString);

StatusJSONImpl is an implementation detail which library users are not meant deal with. The only thing a user of the library should care about is the contract (the Status interface in this case) which is necessarily public and the library authors promise to fulfill. On the other hand, the concrete classes like StatusJSONImpl are not public on purpose in order to prevent consumers from using them and getting tightly coupled to a specific implementation which may change over time. And from the authors' point of view, by coding to an interface they are then free to return any concrete type they wish as long as it fulfills the contract.

If you check the class that is returned from the factory method, it is StatusJSONImpl. But to reiterate, as a user of the library you should need to know or care about that.

Status status = TwitterObjectFactory.createStatus(statusAsString);
status.getClass(); // class twitter4j.StatusJSONImpl

To understand more about why this is done, you can read about static factory methods.

David Good
  • 486
  • 5
  • 8