Good afternoon
In Visual Studio 2010 I am able to add to my solution a new item called in AJAX-enabled WCF service. That will add a new a .svc file.
Later, I have created a method just for debugging purposes:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DataAccessService
{
[WebGet]
[OperationContract]
public MyClass DoWork()
{
var o = new MyClass
{
Id = 1,
FirstName = "Junior",
LastName = "Mayhe"
};
return o;
}
}
When debugging here is the resulting Json string:
{"d":
{"__type":"MyClass:#MyProject",
"Id":1,
"FirstName":"Junior",
"LastName":"Mayhe"
}
}
The question is, what is this "d"?
Is it some result type code for a Json string, and if so, are there other codes?
thanks in advance
It is only "d", and it is intended as protection against some cross-site scripting attacks.
E.g. consider a method that returns an int array of sensitive data (e.g. bank account balances). It can be returned as:
[10000,12300,15000]
Or:
{"d":[10000,12300,15000]}
The problem is that in the first case, there's a (very advanced and obscure but nevertheless real) attack whereby another site can steal this data by including a call to the service in a tag and overriding the JavaScript array constructor. The attack is not possible if the JSON looks like the latter case.
There was some talk within Microsoft to extend the format beyond just "d", but I don't think it ever went anywhere.
Your response is simply getting encapsulated with a parent object called "d". It was introduced in ASP.NET 3.5 web services as a security enhancement to prevent JSON hijacking.
The client proxies generated for your service will strip out the "d" so you will never really even know it was there. But since you're service isn't really going to be consumed for anything other than AJAX requests, you'll have to access your JSON objects through the ".d" property. I would recommend using JSON2 to parse the response, since not all browsers have native JSON support at the time of this writing.
You can read a little more about the security problem here.
Related
I'm implementing JMS in a Spring Boot application. Everything is going well. However I'm very surprised at the tight coupling between JSON messages and Java objects. I am looking for some direction on a more flexible solution.
Going through examples and using the MappingJackson2MessageConverter, everything is great as long as you are sending and receiving in the same application. Under the covers it's extremely tightly coupled to the java object. If I have a simple java object called person:
package acme.receivingapp.dto;
public class Person {
private String firstName;
private String lastName;
...
}
When the JmsTemplate turns that into a message the JSON looks generic enough:
{"firstName":"John", "lastName":"Doe"}
However it includes this property:
"_type" : "acme.superapp.dto.Person"
If the JmsListener isn't using that exact Java class, it throws an exception. That's true even if the class is functionally the same as in this example where it's effectively the same class but just in a different package:
package wonderco.sendingapp.dto;
public class Person {
private String firstName;
private String lastName;
...
}
We will be receiving messages from many external entities from mainframes, python apps, .Net, etc. I cannot require them to include our object types in a _type property.
I could create my own MessageConverter specifically for a Person object, but if we have hundreds of more messages / java classes it would be unwieldy to have so many message converters. I would need to design something more generic that can work for any type of JSON message / java class.
Before I go down the path of designing my own generic solution is there anything more generic that works like Spring RestControllers and Spring RestTemplates in the sense that the JSON messages aren't so tightly coupled to the very specific Java classes? I feel like I can't possibly be the first person trying to crack this nut.
I think I've got a handle on this. I'll try to explain it to hopefully help the next person who is new to Spring / JMS.
As M.Deinum points out, unlike a REST endpoint, a queue could potentially contain many different types of messages. Even if your implementation will only have one type of message per queue. Because queues allow any number of different messages that was the design for the provided MappingJackson2MessageConverter. Because the assumption was made there will always be multiple types of messages, there must be a mechanism to determine how to unmarshal the JSON for different types of messages into the correct type of Java Object.
All the examples you'll find of using a MappingJackson2MessageConverter will have this setup in them:
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTypeIdPropertyName("_type");
That's telling the message converter to set the object type in a property called _type when creating a message or to read the object type from that property when reading a message. There's no magic in that _type property. It's not a standard. It's just what the Spring folks used in their examples and then a bazillion people cut and pasted it. So for your own messages, you can change that to a more appropriate property name if you like. So in my example, I might call the property acme_receivingapp_message_type if I wanted. I would then tell the external entities sending me messages to include that property with the message type.
By default, the MappingJackson2MessageConverter will write the object type into whatever property name you chose (_type or whatever) as the fully qualified class name. In my example, it's acme.receivingapp.dto.Person. When a message is received, it looks at the type property to determine what type of Java object to create from the JSON.
Pretty straightforward so far, but still not very convenient if the people sending me messages are not using Java. Even if I can convince everyone to send me acme.receivingapp.dto.Person, what happens if I refactor that class from Person to Human? Or even just restructure the packages? Now I've got to go back and tell the 1,000 external entities to stop sending the property as acme.receivingapp.dto.Person and now send it as acme.receivingapp.dto.Human?
Like I stated in my original question, the message and Java class are being very tightly coupled together which doesn't work when you are dealing with external systems/entities.
The answer to my problem is right in the name of the **Mapping**Jackson2MessageConverter message converter. The key there is the "mapping". Mapping refers to mapping message types to Java classes which is what we want. It's just that, by default, because no mapping information is provided, the MappingJackson2MessageConverter simply uses the fully qualified java class names for creating and receiving messages. All we need to do is provide the mapping information to the message converter so it can map from friendly message-types (e.g.. "Person") to specific classes within our application (e.g. acme.receivingapp.dto.Person).
If you wanted your external systems/entities that will be sending you messages to simply include the property acme_receivingapp_message_type : Person and you wanted that unmarshalled to an acme.receivingapp.dto.Person object when it's received on your end, you'd setup your message converter like this:
#Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("acme_receivingapp_message_type");
// Set up a map to convert our friendly message types to Java classes.
Map<String, Class<?>> typeIdMap = new HashMap<>();
typeIdMap.put("Person", acme.receivingapp.dto.Person.class);
converter.setTypeIdMappings(typeIdMap);
return converter;
}
That solves the problem of tight coupling between the message type property and Java class names. But what if you'll only be dealing with a single message type in your queue and don't want the people sending messages to have to include any property to indicate the message type? Well MappingJackson2MessageConverter simply doesn't support that. I tried using a "null" key in the map and then leaving the property off the message and unfortunately it doesn't work. I wish it did support that "null" mapping to use when the property wasn't present.
If you have the scenario where your queue will only deal with one type of message and you don't want the sender to have to include a special property to indicate the message type, you'll likely want to write your own message converter. That convertor will blindly unmarshal the JSON to the one java class you'll always be dealing with. Or maybe you opt to just receive it as a TextMessage and unmarshal it in your listener.
Hopefully this helps someone because I found it quite confusing initially.
I'm reacting to this thread because I have exactly the same feeling!
Why spring isn't able to deserialise the event based on the prototype function that implement the #JmsListener ?
If you have a function like
#JmsListener(destination = "#{beanQueue.queueName}")
public void onEvent(MyEvent event) {
// Do what you want
}
Why do we need to explicitly define the _type property that allow to know the java type output? We can extract it from the parameter function.
I don't perform deep search under the hood, but it look reasonable to me
[EDIT] After some debugging and some quick research, I found a solution. I'm not convinced that it's the more elegant solution, but at least it allow to have a kind of generic converter.
Convert all to String
Convert automatically all event to the java.lang.String type, in order to have a generic _type for all consumer
It can be done by encapsulate the actual MappingJackson2MessageConverter
#Bean
public MessageConverter jsonMessageConverter() {
final ObjectMapper objectMapper = new ObjectMapper();
// Setup the object mapper
final MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();
messageConverter.setObjectMapper(objectMapper);
messageConverter.setTargetType(MessageType.TEXT);
messageConverter.setTypeIdPropertyName("_type");
return new MessageConverter() {
#Override
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
try {
final String stringValue = objectMapper.writeValueAsString(object);
return messageConverter.toMessage(stringValue, session);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
#Override
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
return messageConverter.fromMessage(message);
}
};
}
Read all from String
In order to read all from String without need to rewrite all the actual spring implementation, we can take benefit of the ConversionService
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter((Converter<String, MyEvent>) source -> {
try {
return new ObjectMapper().readValue(source, MyEvent.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
});
}
Limitation
There is some limitation, since the event is now transfered as a String, which is not elegant at all..
I don't actually investigate with the org.springframework.jms.support.converter.MessageType that allow to define other type of message.
In addition, it force the client to always define a converter for all event that are listening inside the application.
Using Spring RestTemplate, I'd like to consume a HAL based REST service with a simplified configuration like this:
GET http://my.rest.service/items/123 returns
{
"_links": {
"category": {
"href": "/categories/321"
},
"self": {
"href": "/items/123"
}
},
"name": "my wonderful item"
}
A GET on http://my.rest.service/categories/321 will then accordingly return the category my item is assigned to (which looks quite similar to the JSON above).
What I can do up to now (and what is working :)) is some "manual" link-following:
public Item getItemById(Integer itemId) {
RestTemplate restTemplate = getRestTemplateWithHalMessageConverter();
ResponseEntity<Resource<Budget>> response =
restTemplate.exchange("http://my.rest.service/items/"+itemId,
HttpMethod.GET, getHttpEntity(),
new ParameterizedTypeReference<Resource<Item>>() {}
);
ResponseEntity<Resource<Category>> catResponse =
restTemplate.exchange("http://my.rest.service/" +
response.getBody().getLink("category").getHref(),
HttpMethod.GET, getHttpEntity(),
new ParameterizedTypeReference<Resource<Category>>() {}
);
Item result = response.getBody().getContent();
//^^ Now this is an item with NULL in category field
result.setCategory(catResponse.getBody().getContent());
//And voila, now the category is assigned
return result;
}
(I didn't post the "helper" functions like getRestTemplateWithHalMessageConverter() here as IMHO they are not relevant for this question, especially as they work as expected.)
What I would like to achieve is "auto-following" the links in the HAL response and populate my Java objects respectively.
So, my question is, is there any way to get "automatic" _link following, such that my Item will be fully populated without the second exchange etc.? This is a simple example, but I have more complex objects with many links. Of course, one can assume, that the matching fields exist in the particular classes.
And on bonus question ;) : Can this be used alongside with some kind of caching? If I have 30 items with category 8, I wouldn't like having 30 calls to the category endpoint...
If there is no out-of-the-box solution for both questions (at least I didn't find one...) and I'll have to write my own, I'm fine with that! Just want to make sure I'm not reinventing the wheel just because I missed something...
Thanks a lot!!
You can use Bowman to consume JSON+HAL resources in JAVA. This library greatly simplifies the consumption of resources comparing to RestTemplate as shown in this article.
This library answers the "automatic link following" part :
Our client is a wrapper around Spring HATEOAS and Jackson with a heavy
JPA influence. Retrieving an object from the remote returns a proxy of
the returned object, instrumented using Javassist, whose accessors can
transparently conduct further remote service invocations in accordance
with its HAL links. This allows linked and inline associations to both
be defined in the same way in the client model and greatly simplifies
client code.
After a while a have finished implementing my own solution to my original question (beginning before I was kindly pointed towards Bowman by baxbong).
In case there is anyone else with quite the same needs as I had, you can find my implementation here:
https://github.com/ahuemmer/storesthal
As described there, I will go on and extend it as there is some demand (by me or by others). :) Everyone is, of course, free to open issues or pull requests!
I am trying to publish JSON Message(Object) on to the ActiveMQ queue/topic.
currently i am converting JSON object into String then publishing it.
But i don't want to convert it into String.I don't want to convert it into String instead of that i want to send as it is JSON Object as a Message.
Below is my code
public void sendMessage(final JSONObject msg) {
logger.info("Producer sends---> " + msg);
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
String s = msg.toString();
return session.createTextMessage(s);
// createTextMessage(msg);
}
});
}
Using text on the queue is best practice since you will be able to debug a lot easier as well as not being restricted to the exactly same language/framework or even version of the libraries on the applications on both sides of the queue.
If you really want that hard coupling (i.e. when you are using the queue inside a single application and don't need to inspect messages manually on the queues) you can do it:
instead of return session.createTextMessage(s); do return session.createObjectMessage(msg);
One more thing: Be aware that using JMS ObjectMessage may cause security issues if you don't have 100% control of the code posting messages. Therefore this is not allowed in default ActiveMQ settings. You need to enable this in both client and server settings. For reference, see this page: http://activemq.apache.org/objectmessage.html
Rivets.js proposes to use the adapter.read and adapter.publish functions to get and set properties of a model while defining binders. I have not found an actual benefit of using read/publish when compared to the standard get/set methodology.
Excerpt from documentation:
adapter.read(model, keypath)
adapter.publish(model, keypath, value)
The source code for read and publish from v0.6.10
read: function(obj, keypath) {
return obj[keypath];
},
publish: function(obj, keypath, value) {
return obj[keypath] = value;
}
I wonder if anyone knows about the benefits that read and publish may offer?
I finally figured this out. The answer is as simple as abstracting the get and set functionalities from the binder. This has no real benefit if using rivets as is with the one and only dot (.) binder which it ships with. But this approach comes in very handy when one defines custom adapters.
A good example, like in my case, is when using the rivets-backbone adapter. The model passed to the binder could be a plain old java object or a backbone model. Reading and writing of properties on the object vary based on its type. By using the publish and read functions, this logic gets abstracted from the binders implementation.
I have a Grails service that sends out e-mails using a 3rd-party service by doing a HTTP call:
class EmailService {
def sendEmail(values) {
def valueJson = values as JSON
... // does HTTP call to 3rd party service
}
}
I've written a unit test to test this service (because an integration test spins up Hibernate and the entire domain framework, which I don't need):
#TestFor(EmailService)
class EmailServiceTests {
void testEmailServiceWorks() {
def values = [test: 'test', test2: 'test2']
service.sendEmail(values)
}
}
However, when I execute this unit test, it fails with this exception when it tries to do the as JSON conversion:
org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap
I then re-wrote my unit test to just do the following:
void testEmailServiceWorks() {
def value = [test: 'test', test2: 'test2']
def valueJson = value as JSON
}
And I get the same exception when it tries to do the as JSON conversion.
Does anyone know why I'm getting this exception, and how I can fix it?
Even though you are testing a service, you can apply the #TestMixin(ControllerUnitTestMixin) annotation to your test class to get Grails to set up the JSON converter.
The as JSON magic is created when the domain framework spins up.
You have to either change your test to an integration one or mock the asType.
def setUp(){
java.util.LinkedHashMap.metaClass.asType = { Class c ->
new grails.converters."$c"(delegate)
}
}
Rember to clean up after yourself in the tearDown, you wouldn't want metaprogramming leaks in your test suite.
def tearDown(){
java.util.LinkedHashMap.metaClass.asType = null
}
Edit:
If you come from the future, consider this answer: https://stackoverflow.com/a/15485593/194932
As Grails 3.3.x grails-test-mixins plugin is deprecated. #see migration guide.
For this problem you should implement GrailsWebUnitTest which is coming from Grails Testing Support Framework.
you can initialise the JSON in the setUp() . There are various marshallers which implement ObjectMarshaller , which need to be added to the ConverterConfiguration for JSON conversion to work.
http://grails.github.io/grails-doc/2.4.4/api/index.html?org/codehaus/groovy/grails/web/converters/marshaller/json/package-summary.html
example :
DefaultConverterConfiguration<JSON> defaultConverterConfig = new DefaultConverterConfiguration<JSON>()
defaultConverterConfig.registerObjectMarshaller(new CollectionMarshaller())
defaultConverterConfig.registerObjectMarshaller(new MapMarshaller())
defaultConverterConfig.registerObjectMarshaller(new GenericJavaBeanMarshaller())
ConvertersConfigurationHolder.setTheadLocalConverterConfiguration(JSON.class, defaultConverterConfig);
I just ran into this, and I really didn't want to implement GrailsWebUnitTest as recommended in another answer here. I want to keep my service test as "pure" and lean as possible. I ended up doing this:
void setupSpec() {
defineBeans(new ConvertersGrailsPlugin())
}
void cleanupSpec() {
ConvertersConfigurationHolder.clear()
}
This is how it happens under the hood when you implement GrailsWebUnitTest (via WebSetupSpecInterceptor and WebCleanupSpecInterceptor).
That said, the converters seem to be meant for use in the web tier, primarily for making it easy to transparently return data in different formats from a controller. It's worth considering why the service you're testing needs the converters in the first place.
For example, in my case, someone used the JSON converter to serialize some data to a string so it could be stored in a single field in the database. That doesn't seem like an appropriate user of the converters, so I plan on changing how it's done. Making the converters available in my service test is a temporary solution to allow me to improve our test coverage before I refactor things.
I was getting the same error when trying to unit test a controller that calls "render myMap as JSON". We use Grails 1.3.7 and none of the other solutions worked for me without introducing other problems. Upgrading Grails was not an alternative for us at the moment.
My solution was to use JSONBuilder instead of "as JSON", like this:
render(contentType: "application/json", {myMap})
See http://docs.grails.org/latest/guide/theWebLayer.html#moreOnJSONBuilder
(I realize this is old, but came here in search for a solution and so might others)