Scala (console) has a very useful feature to inspect or dump variables / object values : scala> def b = Map("name" -> "Yudha", "age" -> 27)
b: scala.collection.immutable.Map[java.lang.String,Any] scala> b
res1: scala.collection.immutable.Map[java.lang.String,Any] = Map((name,Yudha), (age,27)) Inside our application, especially in Java programming language (although the techniques below obviously works with any JVM language like Scala and Groovy) sometimes we want to inspect/dump the content of an object/value. Probably for debugging or logging purposes. My two favorite techniques is just to serialize the Java object to JSON and/or XML. An added benefit is that it's possible to deserialize the dumped object representation back to an actual object if you want.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.6.3</version>
</dependency>
Then use it:
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; ..
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void level() throws ServiceException, JsonGenerationException, JsonMappingException, IOException {
MagentoServiceLocator locator = new MagentoServiceLocator();
Mage_Api_Model_Server_HandlerPortType port = locator.getMage_Api_Model_Server_HandlerPort();
String sessionId = port.login("...", "...");
logger.info(String.format("Session ID = %s", sessionId));
Map[] categories = (Map[]) port.call(sessionId, "catalog_category.level", new Object[] { null, null, 2 } );
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
logger.info( mapper.writeValueAsString(categories) );
} Example output : 6883 [main] INFO id.co.bippo.shop.magentoclient.AppTest - [ {
"position" : "1",
"level" : "2",
"is_active" : "1",
"name" : "Gamis",
"category_id" : "3",
"parent_id" : 2
}, {
"position" : "2",
"level" : "2",
"is_active" : "1",
"name" : "Celana",
"category_id" : "5",
"parent_id" : 2
} ]
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2.2</version>
</dependency>
Use it:
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Map; import javax.xml.rpc.ServiceException; import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.thoughtworks.xstream.XStream;
...
@Test
public void infoXml() throws ServiceException, RemoteException {
MagentoServiceLocator locator = new MagentoServiceLocator();
Mage_Api_Model_Server_HandlerPortType port = locator.getMage_Api_Model_Server_HandlerPort();
String sessionId = port.login("...", "...");
logger.info(String.format("Session ID = %s", sessionId));
Map category = (Map) port.call(sessionId, "catalog_category.info",
new Object[] { 3 } );
XStream xstream = new XStream();
logger.info( xstream.toXML(category) );
} Sample output: 5949 [main] INFO id.co.bippo.shop.magentoclient.AppTest - <map>
<entry>
<string>position</string>
<string>1</string>
</entry>
<entry>
<string>custom_design</string>
<string></string>
</entry>
<entry>
<string>custom_use_parent_settings</string>
<string>0</string>
</entry>
<entry>
<string>custom_layout_update</string>
<string></string>
</entry>
<entry>
<string>include_in_menu</string>
<string>1</string>
</entry>
<entry>
<string>custom_apply_to_products</string>
<string>0</string>
</entry>
<entry>
<string>meta_keywords</string>
<string>gamis, busana muslim</string>
</entry>
<entry>
<string>available_sort_by</string>
<string></string>
</entry>
<entry>
<string>url_path</string>
<string>gamis.html</string>
</entry>
<entry>
<string>children</string>
<string></string>
</entry>
<entry>
<string>landing_page</string>
<null/>
</entry>
<entry>
<string>display_mode</string>
<string>PRODUCTS</string>
</entry>
<entry>
<string>level</string>
<string>2</string>
</entry>
<entry>
<string>description</string>
<string>Gamis untuk muslimah</string>
</entry>
<entry>
<string>name</string>
<string>Gamis</string>
</entry>
<entry>
<string>path</string>
<string>1/2/3</string>
</entry>
<entry>
<string>created_at</string>
<string>2010-12-24 11:37:41</string>
</entry>
<entry>
<string>children_count</string>
<string>0</string>
</entry>
<entry>
<string>is_anchor</string>
<string>1</string>
</entry>
<entry>
<string>url_key</string>
<string>gamis</string>
</entry>
<entry>
<string>parent_id</string>
<int>2</int>
</entry>
<entry>
<string>filter_price_range</string>
<null/>
</entry>
<entry>
<string>all_children</string>
<string>3</string>
</entry>
<entry>
<string>is_active</string>
<string>1</string>
</entry>
<entry>
<string>page_layout</string>
<string></string>
</entry>
<entry>
<string>image</string>
<null/>
</entry>
<entry>
<string>category_id</string>
<string>3</string>
</entry>
<entry>
<string>default_sort_by</string>
<null/>
</entry>
<entry>
<string>custom_design_from</string>
<null/>
</entry>
<entry>
<string>updated_at</string>
<string>2010-12-24 11:37:41</string>
</entry>
<entry>
<string>meta_description</string>
<string>Jual baju gamis untuk muslim</string>
</entry>
<entry>
<string>custom_design_to</string>
<null/>
</entry>
<entry>
<string>path_in_store</string>
<null/>
</entry>
<entry>
<string>meta_title</string>
<string>Gamis</string>
</entry>
<entry>
<string>increment_id</string>
<null/>
</entry>
</map> Which one is better? I personally prefer JSON, but fortunately, you always have a choice. :-)
b: scala.collection.immutable.Map[java.lang.String,Any] scala> b
res1: scala.collection.immutable.Map[java.lang.String,Any] = Map((name,Yudha), (age,27)) Inside our application, especially in Java programming language (although the techniques below obviously works with any JVM language like Scala and Groovy) sometimes we want to inspect/dump the content of an object/value. Probably for debugging or logging purposes. My two favorite techniques is just to serialize the Java object to JSON and/or XML. An added benefit is that it's possible to deserialize the dumped object representation back to an actual object if you want.
JSON Serialization with Jackson
Depend on Jackson (using Maven):<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.6.3</version>
</dependency>
Then use it:
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; ..
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void level() throws ServiceException, JsonGenerationException, JsonMappingException, IOException {
MagentoServiceLocator locator = new MagentoServiceLocator();
Mage_Api_Model_Server_HandlerPortType port = locator.getMage_Api_Model_Server_HandlerPort();
String sessionId = port.login("...", "...");
logger.info(String.format("Session ID = %s", sessionId));
Map[] categories = (Map[]) port.call(sessionId, "catalog_category.level", new Object[] { null, null, 2 } );
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
logger.info( mapper.writeValueAsString(categories) );
} Example output : 6883 [main] INFO id.co.bippo.shop.magentoclient.AppTest - [ {
"position" : "1",
"level" : "2",
"is_active" : "1",
"name" : "Gamis",
"category_id" : "3",
"parent_id" : 2
}, {
"position" : "2",
"level" : "2",
"is_active" : "1",
"name" : "Celana",
"category_id" : "5",
"parent_id" : 2
} ]
XML Serialization with XStream
As a pre-note, XStream can also handle JSON with either Jettison or its own JSON driver, however people usually prefer Jackson than XStream for JSON serialization. Maven dependency for XStream:<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2.2</version>
</dependency>
Use it:
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Map; import javax.xml.rpc.ServiceException; import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.thoughtworks.xstream.XStream;
...
@Test
public void infoXml() throws ServiceException, RemoteException {
MagentoServiceLocator locator = new MagentoServiceLocator();
Mage_Api_Model_Server_HandlerPortType port = locator.getMage_Api_Model_Server_HandlerPort();
String sessionId = port.login("...", "...");
logger.info(String.format("Session ID = %s", sessionId));
Map category = (Map) port.call(sessionId, "catalog_category.info",
new Object[] { 3 } );
XStream xstream = new XStream();
logger.info( xstream.toXML(category) );
} Sample output: 5949 [main] INFO id.co.bippo.shop.magentoclient.AppTest - <map>
<entry>
<string>position</string>
<string>1</string>
</entry>
<entry>
<string>custom_design</string>
<string></string>
</entry>
<entry>
<string>custom_use_parent_settings</string>
<string>0</string>
</entry>
<entry>
<string>custom_layout_update</string>
<string></string>
</entry>
<entry>
<string>include_in_menu</string>
<string>1</string>
</entry>
<entry>
<string>custom_apply_to_products</string>
<string>0</string>
</entry>
<entry>
<string>meta_keywords</string>
<string>gamis, busana muslim</string>
</entry>
<entry>
<string>available_sort_by</string>
<string></string>
</entry>
<entry>
<string>url_path</string>
<string>gamis.html</string>
</entry>
<entry>
<string>children</string>
<string></string>
</entry>
<entry>
<string>landing_page</string>
<null/>
</entry>
<entry>
<string>display_mode</string>
<string>PRODUCTS</string>
</entry>
<entry>
<string>level</string>
<string>2</string>
</entry>
<entry>
<string>description</string>
<string>Gamis untuk muslimah</string>
</entry>
<entry>
<string>name</string>
<string>Gamis</string>
</entry>
<entry>
<string>path</string>
<string>1/2/3</string>
</entry>
<entry>
<string>created_at</string>
<string>2010-12-24 11:37:41</string>
</entry>
<entry>
<string>children_count</string>
<string>0</string>
</entry>
<entry>
<string>is_anchor</string>
<string>1</string>
</entry>
<entry>
<string>url_key</string>
<string>gamis</string>
</entry>
<entry>
<string>parent_id</string>
<int>2</int>
</entry>
<entry>
<string>filter_price_range</string>
<null/>
</entry>
<entry>
<string>all_children</string>
<string>3</string>
</entry>
<entry>
<string>is_active</string>
<string>1</string>
</entry>
<entry>
<string>page_layout</string>
<string></string>
</entry>
<entry>
<string>image</string>
<null/>
</entry>
<entry>
<string>category_id</string>
<string>3</string>
</entry>
<entry>
<string>default_sort_by</string>
<null/>
</entry>
<entry>
<string>custom_design_from</string>
<null/>
</entry>
<entry>
<string>updated_at</string>
<string>2010-12-24 11:37:41</string>
</entry>
<entry>
<string>meta_description</string>
<string>Jual baju gamis untuk muslim</string>
</entry>
<entry>
<string>custom_design_to</string>
<null/>
</entry>
<entry>
<string>path_in_store</string>
<null/>
</entry>
<entry>
<string>meta_title</string>
<string>Gamis</string>
</entry>
<entry>
<string>increment_id</string>
<null/>
</entry>
</map> Which one is better? I personally prefer JSON, but fortunately, you always have a choice. :-)
waw.. nyambungnya cuman dikit.. ga ngertinya banyak he..
ReplyDeleteHi,
ReplyDeleteJust to add while writing Serializable class , its good practice to put a Seriazlizable alert in file so that when some one else add a new field in the class he must ensure that field is either transient or Serializable , so that Serializability of class should not break.
Thanks
Javin
Why String is immutable in Java
Good readingg your post
ReplyDelete