JSON_Adapter
Project Goal
Develope an adapter to expose NexJ Express Server objects using JSON
Current Status: Project Completed
Project Phases
Phase 1: Design Proposal (Done)
- Get requirements from NexJ
- Incorporate requirements from NexJ into Design of JSON Adapater
- Proposal proposal for review, make changes as by NexJ until approved
Phase 2: Coding (Done)
- JSONMarshaller
- Develop marshaller to transform NexJ Server Objects into JSON representation
- JSONUnmarshaller
- Develop an marshaller to transform JSON representation into NexJ Server Objects
- JSON Server
- Develop a JSON Server to expose NexJ Server objects in JSON
- Demo application that interacts with the Server using JSON
- Read Server Objects
- Update Server Objects
- Create Server objects
Phase 3: Code Review 1 (Done)
- Send patch to NexJ for review
Phase 4: Make Changes as per Code Review 1 (Done)
- Refactor JSONSever and TextServer to inherit from GenericCharacterStreamHTTPServer
- Optimize marshaling of nested Pair objects
- Rename variables and methods as per NexJ Developer's Guide
Phase 5: Code Review 2(Done)
- Send patch to NexJ for review
Phase 6: Apply Changes per Code Review 2 (Done)
- Minor Clean Up
- Removed unnecessary files
- Ensure all files use CRLF line-endings
- Add Servlet Mapping to cert/web.xml
- GenericCharacterStreamServer
- Use
abstract String getType()
for creating error codes - Use
getLogger()
for lazy initialization of logger
- Use
- TextServer
- Members should be protected
- JSONWriter
- Methods names should start with "write"
- JSONMarshaller
- Remove unused methods
- Remove
isReferencable()
, do lookup in TransferObject Marshaller
- JSONUnmarshaller
- Use
JSONLookup
to find unmarshllers - Create
DetachableByteArrayOutputStream
- Change logic in
Base64Util.decode(String)
- Use
Base64Util.decode(String)
to decode 64 streams - Only TO unmarshaller should use
remove()
otherwise useget()
on m_jsonMap - Change instances of
Collection.toArray()
to usetoArray(new Object[size])
- Use
Phase 7: Code Review 3 (Done)
- Send patch to NexJ for review
Phase 8: Apply Changes per Code Review 3 (Done)
- JSONWriter.java:
- Can a
StringBuilder
be used instead of aStringBuffer
? Maybe the same change can be done inTextMarshaller
as well? The member field can still be calledm_buffer
. UsingStringBuilder
instead ofStringBuffer
avoids the synchronization overhead. - writeString: remove the unnecessary conversion to a character array; the length can be accessed via
String.length()
.
- Can a
- JSONMarshaller.java
- Can you fill in the comment for parameter
"writer"
on method"marshal"
of interfaceMarshaller
? It is currently marked withTODO
. - You can use the string id
err.rpc.mshType
instead oferr.rpc.json.mshType
- Can you define the
Timestamp
marshaller first, then thejava.util.Date
marshaller? Vassiliy wanted the default framework type’s marshaller first, followed by its synonyms.
- Can you fill in the comment for parameter
- JSONParser.java
- Putting parts of the error message in the error arguments Object array that is passed to
fail()
isn’t localizable. The error message should be part of the value of the string id. String ids are stored in the*.strings files
. For string ids used by Java code, the .strings files are incore/src/nexj/core/meta/sys
. You need to ensure that there is an entry in this file for each id that you use. These are then translated into French (and possibly other languages) by people who specialize in translating software interfaces. The only things passed in the error arguments Object array should be data. - There should be a blank line before
break
andreturn
statements.
- Putting parts of the error message in the error arguments Object array that is passed to
- JSONUnmarshaller.java
- For the
castTo*
methods, can you rename them toget*
and have them take aString sKey
argument, which is the key to lookup inm_valueMap
? This will more closely follow what Vassiliy intended when he said “Rather than directly type casting values retrieved from json map, you can have unmsh accessor methods for the common types, which can also do error checking, so that one does not get a generic type cast error and wonder what went wrong and where.” parseObject()
: I don’t think you need separate branches of code for handling the first key in the iterator and subsequent keys. Also, for iteration, preferfor()
towhile()
.
- For the
- JSONUnmarshallerException.java
- The overload with
(String sExpected, Class actual)
isn’t localizable. Remove this overload and use the(String sErrCode, Object[] argArray)
constructor. InJSONUnmarshaller get*
methods, pass anObject[]
of length two for theargArray
. Ensure that both are strings. - Please add a string for err.rpc.json.unmsh.CastException to en.strings in core/src/nexj/core/meta/sys. The various parts of the string id should all start with lowercase letters, e.g. CastException à castException. Use a meaningful name instead of “CastException”—CastException is what it is, not what the error is.
- The overload with
- JSONTests.java
testSerializeException
doesn’t need to initialize themarshaller
andunmarshaller
: they are initialized already bysetUp()
, which is run before eachtest*()
method.- please remove the parts of tests that are duplicated. For example, in
testServerObjects()
you test the serialization of a Symbol calledsym
, aPrivilegeSet
of “480000”, and aPCodeFunction
withcode
0, 1, 2. But these have already been tested by thetestSerializeRequestCheckJSON
which uses the m_request object initialized by the superclass. - Use
Primitive.createInteger
,Primitive.createLong
, etc. instead ofnew Integer(…), new Long(…)
, etc. where possible.
Phase 9: Code Review 4 (Done)
- Send patch to NexJ for review
Phase 10: Apply Changes per Code Review 4 (Done)
- The
m_tokenValue
used in some of the error messages won’t always be populated. For example, inparseArray()
,m_tokenValue
is used, but it will only be valid if the current token isTOKEN_ATOM
.
- The
boolean.invalidToken
error message can be removed and you can use justerr.parse.unexpectedToken
instead, as one doesn’t know for certain that the input is aBoolean
. Same fornull.invalidToken
andnumber.invalidToken
.
-
parseObject()
: theif (sKey == null)
check can never succeed, becauseinstanceof
should return false if its argument isnull
.
Phase 11: Code Review 5 (Done)
- Send code for review
Links
JSON
http://www.json.org