Saturday, 13 September 2014

Spring MVC Test cases with Annotated Beans Using Mockito

Annotations make java developer's life easy and also it feels like annotation based classes are complex for unit testing. But in reality it is quite simple. There are couple of ways through which you can test autowired/spring based classes.

Method 1:
You can use AnnotationConfigApplicationContext to load application context. Instantiate application context, register annotated classes and test your methods. Here is the sample code

package com.bala.controller;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.bala.service.ArticleService;
public class ArticleControllerSpringUtils {
private AnnotationConfigApplicationContext appCtx;
@Before
public void initializeAnnotationContext() {
appCtx = new AnnotationConfigApplicationContext();
}
@Test
public void testSampleMethod() {
initializeAnnotationContext();
appCtx.register(ArticleService.class);
appCtx.register(ArticleController.class);
appCtx.refresh();
ArticleController articleController = appCtx
.getBean(ArticleController.class);
System.out.println(articleController.getAll());
}
}
Method 2:
Even though preceding method is an easiest way to test annotation based spring classes, if your test case becomes complex and if you want to mock actual request etc, you better move to mocking framework instead of basic one. I have used mockito with spring-test to mock actual requests with spring beans. Here is the sample code

package com.bala.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.bala.domain.Article;
import com.bala.service.ArticleService;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("/spring/rest-servlet.xml")
public class ArticleControllerTest {
private final static Logger logger = LoggerFactory
.getLogger(ArticleControllerTest.class);
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@InjectMocks
private ArticleController articleControllerTest;
// TODO Spy all the beans if you want to mock them otherwise use @Mock
@Spy
private ArticleService articleService;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
MockitoAnnotations.initMocks(this);
}
@Test
public void getAll() throws Exception {
System.out.println(articleControllerTest.getAll());
}
@Test
public void getAllByMockingRequest() throws Exception {
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.get("/article/").accept(
MediaType.APPLICATION_JSON)).andReturn();
logger.info(result.getResponse().getContentAsString());
}
@Test
public void getArticleByMockingRequest() throws Exception {
String articleId = "1";
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.get("/article/" + articleId).accept(
MediaType.APPLICATION_JSON)).andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void putArticleByMockingRequest() throws Exception {
String articleId = "1";
Article article = new Article("1", "Test", "Sample Aticle");
ObjectMapper mapper = new ObjectMapper();
byte[] content = mapper.writeValueAsBytes(article);
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.put("/article/" + articleId)
.accept(MediaType.APPLICATION_JSON).content(content))
.andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void postArticleByMockingRequest() throws Exception {
Article article = new Article("1", "Test", "Sample Aticle");
ObjectMapper mapper = new ObjectMapper();
byte[] content = mapper.writeValueAsBytes(article);
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.post("/article/")
.accept(MediaType.APPLICATION_JSON).content(content))
.andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void deleteArticleByMockingRequest() throws Exception {
String articleId = "1";
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.delete("/article/" + articleId).accept(
MediaType.APPLICATION_JSON)).andReturn();
System.out.println(result.getResponse().getContentAsString());
}
}
In the above sample code we have used spy to mock real objects, if you just want to mock it you can use mock annotation instead of spy.

For this you need mockito and spring-test jars. Following are the minimal poms for the both respectively.
     <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
  </dependency>
            <dependency>
           <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.0.0.RELEASE</version>
          <scope>test</scope>
  </dependency>

Here is the complete code with both the testing methodologies.
spring-test-template using mockito

Wednesday, 10 September 2014

Extjs 4 : Delegating Events

Though ExtJS supports excellent event handling mechanism, sometimes we may want to handle custom events on some HTML components. For example if you want to handle hyperlink click whereas hyperlink is embedded in html code(using html tag or xtemplate), then you may need to delegate events to the component that you have created using 'delegate'. You can use simple hack to handle this.

  • Create HTML text using html tag or xtemplate. 
  • Assign classname/id to the component to which you want to attach an event. 
  • Attache event to the Ext body and delegate to the specific class/id show in below.
  • Make sure that class name or id is unique. 

Here is the fiddle to fiddle around with it.
Sample snippet
values = [{
id : 'v1',
name : 'Value1'
}, {
id : 'v2',
name : 'Value2'
}, {
id : 'v3',
name : 'Value3'
}, {
id : 'v4',
name : 'Value4'
}, {
id : 'v5',
name : 'Value5'
}];
var tpl = new Ext.XTemplate(
'<p>Values: ',
'<tpl for=".">',
'<div style="display: inline-block" data-valueid="{id}" class="values-class">{name}</div><br/>',
'</tpl></p>');
var panel = Ext.create('Ext.panel.Panel', {
renderTo : Ext.getBody()
,
});
tpl.overwrite(panel.body, values);
var el = Ext.getBody();
el.on('mouseover', function(e, t, eOpts) {
alert(t.getAttribute('data-valueid'));
}, this, {
delegate : '.values-class'
});

Friday, 29 August 2014

ExtJS4 Dynamic Grid

In the MV* patterns, model refers to the fixed state of content. If state changes then the benefit that comes out of this model is trivial. Some times it could be a case that model is dynamic, in such a case ExtJS grid should be constructed dynamically. Here is how the sample code goes...

ExtJS4 grid has a method called reconfigure which takes store and columns as input arguments and restructures grid. These columns and store depends on the field data which a part of model. Since model is dynamic lets create field data dynamically along with the actual data and send it to the server.



this.grid = Ext.widget('grid', {
store: null,
columns: null
});
Ext.Ajax.request({
url: '/dynamicGridData',
callback: this.buildDynamicGrid,
scope: this
});
buildDynamicGrid: function(options, success, response) {
var data = Ext.decode(response.responseText);
var fielddata = new Array();
var columndata = new Array();
Ext.Array.forEach(data.headers, function(header) {
Ext.Array.push(columndata, {
text: header.text,
dataIndex: header.dataIndex
});
Ext.Array.push(fielddata, {
name: header.dataIndex
});
});
var store = Ext.create('Ext.data.ArrayStore', {
fields: fielddata,
data: data.rows
});
var columns = columndata
this.grid.reconfigure(store, columns)
}
view raw DynamicGrid.js hosted with ❤ by GitHub
Here is the structure from server
public class DynamicGrid {
private List
headers;
private List fields;
private List> rows;
public List> getRows() {
return rows;
}
public void setRows(List> rows) {
this.rows = rows;
}
public List getFields() {
return fields;
}
public void setFields(List fields) {
this.fields = fields;
}
public List
getHeaders() {
return headers;
}
public void setHeaders(List
headers) {
this.headers = headers;
}
public void addField(String string) {
if (this.fields == null) {
this.fields = new ArrayList<>();
}
this.fields.add(string);
}
public void addHeader(Header header) {
if (this.headers == null) {
this.headers = new ArrayList<>();
}
this.headers.add(header);
}
public void addRow(List row) {
if (this.rows == null) {
this.rows = new ArrayList<>();
}
this.rows.add(row);
}
}
public class Header {
private String text;
private String dataIndex;
public Header(String text, String field) {
this.text = text;
this.dataIndex = field;
}
}

Thursday, 21 August 2014

ExtJS4: Missing HasOneInstance While Decoding JSON

Sometime ExtJS plays dumb role in throwing exceptions. It ignores exceptions instead of handling them, especially while dealing with associations. 

Whenever ExtJs loads data throw proxy into model, it decodes json data into respective models including associations. In case of hasMany association it creates <association-name>Store and in case of hasOne association, it creates <association-name>HasOneInstance store and decodes data into corresponding stores. 

But here are some cases where ExtJS may miss these conversions without throwing any error. 
  • If your association name is in camel case and if you have defined its association with its basic properties like type and model, then ExtJs generates rest of the properties by default. While generating default properties it converts camel case text into lower case and associate it to the association. 
   For example if you have defined a hasOne association as follows, 
       associations: [{ type: 'hasOne', model: 'homeAddress' }]
  It generates association_key as homeaddress (converts camel case into lower case) and maps this key      with the json object which will be in camel case. Because of mismatch in name, it doesn't create homeAddressHasOneInstance object in the parent object. 
  • If you don't use association's model explicitly and miss its inclusion in controller then ExtJS doesn't complain about the model and store conversion will not happen for that association. 

Saturday, 16 August 2014

Logging in Eclipse Birt

Birt is one of the best open source projects that provides data visualization and reports for rich internet applications. But logging is one of the common problems while developing reports in BIRT report engine. Here is the small hack that I have used in birt global script to log my data.
  • Select initialize Script in birt(Select report, open report in Birt Report Design perspective select report and go to script tag, on the top of the screen, you can select initialize script). 
  • Since Birt uses java logging, you can use following script in initialize script to log the message
  • 
    
    
    
    importPackage(Packages.java.lang); function log(msg){ System.out.println("Info : " + msg); } reportContext.setGlobalVariable("log", log)
    
    
  • Use log function in other scripts to log message. 
Note : If you cant find the console in eclipse, open eclipse in console mode. (To open eclipse in console mode, open eclipsec.exe instead of eclipse.exe). 

You can also use Log4j properties in birt reporting. Here is the detailed explanation.   

Wednesday, 13 August 2014

Eclipse : Server Error - Resource **** Does Exist

Today I was trying to configure my development environment in newly released Eclipse version: LUNA. Suddenly I faced a  problem in configuring server. I was just using simple tomcat which I had used it like hundred times. Only change I did was to modify small entry in some configuration file and then eclipse started crying. I tried many combinations, changed different tomcat servers and to test the tomcat server I moved into older eclipse. Finally I found that its a bug in eclipse. Its not with the new eclipse version but there with every eclipse version.

Here is the error...
Reason:
Could not save because file has been modified since the start of editing eclipse



Here is the solution to my problem. Its the name that has caused the problem. While naming the server I have used server location as the name of the server.

I used server name as 'C:\NGPS\apache-tomcat-7.0.27'  and because of the back slashes in the name, it was failing to add new server. Moreover message that was throwing matched in my case and I ended up in doing permutations and combinations. Simple workaround for this problem is to change tomcat name to a simple string with alpha-numerics. Once you change the name, close 'Add new server window' and try to add it agian.

Wednesday, 2 July 2014

ExtJS4 : Copying data from one grid to another.

Copying content into clipboard is a security hole. As a result no simple javascript method is available to write content into clipboard. Except IE, no other browser supports this without any plugins/flash. But if you just want to copy one row of grid and paste it into another grid you can use following hack.(Two grid stores should use same model). 

  • Select a row and provice ExtJS context menu, in action get selected record. It will be in the form of model. Convert this model object into JSON object using getData(true) method on the model. It converts model object into json including association data. 
  • Now your task is to persist this data in user's environment. For this you can use HTML5 web storage. It is simple, faster and secure. But it doesn't work on IE7 and earlier versions.
                   localStorage.setItem("json-object", model.getData(true));
  • Above code stores model object into client's browser in the form of string. 
  • When you wan to handle paste, fetch the stored data string and decode into JSON object. 
                  var jsonObject =  Ext.Deode(localStorage.getItem("json-object"));
  • After retrieving jsonObject convert this back in to model and push it into grid's store. 
            Check this to convert jsonObject into model.


Extjs4 : Converting JSON Object into model

ExtJS provides getData(true) method on model to convert model object into JSON Object including associations. But other way is not a straight forward thing in ExtJS4. If you have JSON and want to convert into model, one dirty way could be create a store with memory proxy, input JSON object as data object and access first record in the store. But this method is not always fruitful. If your JSON has associated data, this method will not work properly. Especially in case of hasOne association case, it never creates *HasOneInstance objects using this method.

I found similar API in Sencha touch 2.2.1 and modified a bit to make it work in ExtJS 4.2.1

  • Write following functions in ExtJS model.
  • Create a model and use setData(JSON Object)
  • It returns model with populated data along with the hasMany, hasOne associations. 
  • setData : function(rawData) {
    var me = this;
    var fields = me.fields.items;
    var ln = fields.length;
    var isArray = Ext.isArray(rawData);
    var data = me.data = {};
    var i;
    var field;
    var name;
    var value;
    var convert;
    var id;
    if (!rawData) {
    return me;
    }
    for (i = 0; i < ln; i++) {
    field = fields[i];
    name = field.name;
    convert = field.convert;
    if (isArray) {
    value = rawData[i];
    } else {
    value = rawData[name];
    if (typeof value == 'undefined') {
    value = field.defaultValue;
    }
    }
    if (convert) {
    value = field.convert(value, me);
    }
    data[name] = value;
    }
    id = me.getId();
    if (me.associations.length) {
    me.handleInlineAssociationData(rawData);
    }
    return me;
    },
    handleInlineAssociationData : function(data) {
    var associations = this.associations.items;
    var ln = associations.length;
    var i;
    var association;
    var associationData;
    var reader;
    var proxy;
    varassociationKey;
    data = Ext.apply({}, data, this.raw);
    for (i = 0; i < ln; i++) {
    association = associations[i];
    associationKey = association.associatedKey;
    associationData = data[associationKey];
    if (associationData) {
    reader = association.getReader();
    if (!reader) {
    proxy = association.associatedModel.getProxy();
    if (proxy) {
    reader = proxy.getReader();
    } else {
    reader = new Ext.data.JsonReader({
    model : association.getAssociatedModel()
    });
    }
    }
    association.read(this, reader, associationData);
    }
    }
    }
    Source can be found @https://github.com/Balagangadhar/ExtJS4-Misc/blob/master/ExtJS4JsonObjectToModel.js


Thursday, 12 June 2014

MxGraph Indicator Diagram

Recently I have used mxGraph to draw an indicator diagram to indicate active panel in a wizard. Event though mxGraph has a documentation, I found it difficult while working with this framework.

By default mxCell allows one lable per cell. If you need more than that we can insert labels using insertCell or insertVertex. In this example I needed two lables(One for state and other is for name of the state), so I have used vertex and inserted one more vertex to the parent vertex. 

Ext.define('MyApp.view.ux.Indicator', {
extend : 'Ext.Container',
xtype : 'wizindicator',
title : 'Indicator Highlighter',
initComponent : function() {
this.mainLayoutId = Ext.id();
if (Ext.isEmpty(this.indicatorItems)) {
this.indicatorItems = ['Indicator0', 'Indicator1', 'Indicator2',
'Indicator3', 'Indicator4'];
}
this.indicators = [];
Ext.apply(this, {
html : '
'
});
this.callParent(arguments);
},
listeners : {
'afterrender' : function(mainLayout, eOpts) {
this.renderDiagrammer(mainLayout);
}
},
renderDiagrammer : function(mainLayout) {
if (!mxClient.isBrowserSupported()) {
mxUtils.error('Browser is not supported!', 200, false);
} else {
var graph = new mxGraph(document
.getElementById(mainLayout.mainLayoutId));
mainLayout.graph = graph;
graph.setEnabled(false);
graph.getStylesheet().putCellStyle('indicator-style',
mainLayout.getIndicatorStyle(graph));
graph.setHtmlLabels(true);
graph.isCellFoldable = function(cell) {
return false;
}
if (!Ext.isEmpty(this.indicatorItems)) {
for (var i = 0; i < mainLayout.indicatorItems.length; i++) {
var indicator = mainLayout.createIndicator(i,
mainLayout.indicatorItems[i], graph, mainLayout);
this.indicators.push(indicator);
}
}
this.createEdges(mainLayout.indicators, graph);
this.executeLayout(graph);
}
},
getIndicatorStyle : function(graph) {
var indicatorStyle = graph.getStylesheet().getDefaultVertexStyle();
delete indicatorStyle[mxConstants.STYLE_STROKECOLOR];
delete indicatorStyle[mxConstants.STYLE_FILLCOLOR];
indicatorStyle[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_ELLIPSE;
indicatorStyle[mxConstants.STYLE_PERIMETER] = mxPerimeter.EllipsePerimeter;
indicatorStyle[mxConstants.STYLE_STROKECOLOR] = '#d3d3d3';
return indicatorStyle;
},
executeLayout : function(graph) {
graph.getModel().beginUpdate();
var layout = new mxHierarchicalLayout(graph,
mxConstants.DIRECTION_WEST, false);
try {
layout.execute(graph.getDefaultParent());
} finally {
graph.getModel().endUpdate();
}
},
createIndicator : function(index, name, graph, mainLayout) {
if (index === 0) {
// TODO to fix Hierachical layout initial point
var labelXPos = 1.8;
} else {
var labelXPos = 0.5;
}
graph.getModel().beginUpdate();
try {
var indicatorSize = mainLayout.indicatorSize | 20;
var vertex = graph.insertVertex(graph.getDefaultParent(), null,
index, 0, 0, indicatorSize, indicatorSize);
var vertexSecondaryLabel = graph
.insertVertex(vertex, null, name, labelXPos, 1, 0, 0,
'align=center;verticalAlign=top;', true);
} finally {
graph.getModel().endUpdate();
}
var indicator = new Indicator(index, name, vertex);
return indicator;
},
createEdges : function(indicators, graph) {
var edgeStyle = 'startArrow=none;endArrow=none;strokeWidth=6;strokeColor=#d3d3d3';
if (!Ext.isEmpty(indicators)) {
for (var i = 1; i < indicators.length; i++) {
graph.getModel().beginUpdate();
try {
var edge = graph.insertEdge(graph.getDefaultParent(), null,
null, indicators[i - 1].vertex,
indicators[i].vertex, edgeStyle);
} finally {
graph.getModel().endUpdate();
}
}
}
},
highlightIndicator : function(index) {
if (!Ext.isEmpty(this.indicators) && index <= this.indicators.length) {
var highlightStyle = 'fillColor=#A3C0EE';
for (var i = 0; i < this.indicators.length; i++) {
if (i === index) {
this.graph.getModel().setStyle(this.indicators[i].vertex,
highlightStyle);
} else {
this.graph.getModel().setStyle(this.indicators[i].vertex,
null);
}
}
} else {
console.error('Index out of bound');
}
}
});
function Indicator(id, name, vertex) {
this.id = id;
this.name = name;
this.vertex = vertex;
}
view raw Indicator.js hosted with ❤ by GitHub



Source can also be found @ https://github.com/Balagangadhar/ExtJS4-Misc/blob/master/Indicator.js

Tuesday, 18 March 2014

Extjs 4 : Converting treestore into store using associations.

Extjs doesn't support updating tree by keeping nodes in its own hierarchy. treestore.sync90 function only sends updated nodes to the server as individual models. But sometimes we may need to send tree structure in the form of tree to the server(Ofcourse only updated nodes).

For example consider following tree,
Parent1
  • Child1
  • Child2
  • Child3
Parent2
  • Chld4
  • Child5
 If  child2 and child5 are dirty records and if we fire treestore.sync(), it only sends child2 and child5 models as data. We loose the context of parent. We may not know for which parent this child belongs to. In such a case you can use following model and code snippet to convert your tree into model with associated models.

Each node will have subtree models as associated model and using following function, you can convert modified tree nodes into associated-model store. This store is a plain store with associated models. Now you can send this model to the server
(For more info on sending updated model associations to the server viz following blog post
http://balu-learnings.blogspot.in/2014/03/extjs-4-sending-updated-models-to.html ).

model :

Ext.define('App.model.treegridsample', {
    extend : 'Ext.data.Model',
    fields : [ {
        name : 'id',
        useNull : true,
        defaultValue : ''
    }{
        name : 'text'
    }{
        name : 'leaf',
        persist : false
    }],

    associations : [ {
        type : 'hasMany',
        model : 'App.model.treegridsample',
        name : 'children'
    }
});


CustomTree.js
  
Ext.define('App.view.common.CustomTree', {
 extend : 'Ext.tree.Panel',
 convertToStore : function(model) {
  if (this.getStore() === null) {
   return null;
  }
  var rootNode = this.getStore().getRootNode();
  model = model || Ext.getClassName(this.getStore().getRootNode());
  dataStore = this.convertNodeToStore(rootNode, model);
  return dataStore.childrenStore;
 },
convertNodeToStore : function(rootNode, model) {
 var record = Ext.create(model);
 record.data = rootNode.data;
 if (record.childrenStore === null || typeof record.childrenStore === 'undefined') {
  record.childrenStore = Ext.create('Ext.data.Store', {
   model : model
  });
 }
 for (var i = 0; i < rootNode.childNodes.length; i++) {
  var cNode = rootNode.childNodes[i];
  var child = this.convertNodeToStore(cNode, model);
  if (cNode.dirty || cNode.phantom) {
   record.childrenStore.add(child);
   rootNode.setDirty();
  }
 }
 return record;
}


Source can be found@ https://github.com/Balagangadhar/ExtJS4-Misc/blob/master/CustomTree.js

Extjs 4 : Sending updated models to server along with associations (has many)

Model- Association is one of the beautiful features of extjs4. Sencha documentation has plenty of examples on 'how to read association' but it doesn't have official documentation on 'how to update model along with its association' which is also a required feature most of the times.


Copy following code snippet in a javascript file and include it in your JSP/html page after extjs framework file inclusion.

<script type="text/javascript" src="extjs4/ext-all-dev.js"></script>
<script type="text/javascript" src="ext-model-assoc-override.js"></script>


Source : sencha forum topic.
Detailed example : http://stackoverflow.com/questions/9871440/extjs-store-hasmany-belongsto-and-update-process-howto


Ext.data.writer.Json.override({
/*
* This function overrides the default implementation of json writer. Any hasMany relationships will be submitted
* as nested objects. When preparing the data, only children which have been newly created, modified or marked for
* deletion will be added. To do this, a depth first bottom -> up recursive technique was used.
*/
getRecordData: function(record) {
//Setup variables
var me = this, i, association, childStore, data = record.data;
//Iterate over all the hasMany associations
for (i = 0; i < record.associations.length; i++) {
association = record.associations.get(i);
data[association.name] = null;
childStore = record[association.storeName];
//Iterate over all the children in the current association
childStore.each(function(childRecord) {
if (!data[association.name]){
data[association.name] = [];
}
//Recursively get the record data for children (depth first)
var childData = this.getRecordData.call(this, childRecord);
/*
* If the child was marked dirty or phantom it must be added. If there was data returned that was neither
* dirty or phantom, this means that the depth first recursion has detected that it has a child which is
* either dirty or phantom. For this child to be put into the prepared data, it's parents must be in place whether
* they were modified or not.
*/
if (childRecord.dirty | childRecord.phantom | (childData != null)){
data[association.name].push(childData);
record.setDirty();
}
}, me);
/*
* Iterate over all the removed records and add them to the preparedData. Set a flag on them to show that
* they are to be deleted
*/
Ext.each(childStore.removed, function(removedChildRecord) {
//Set a flag here to identify removed records
removedChildRecord.set('forDeletion', true);
var removedChildData = this.getRecordData.call(this, removedChildRecord);
data[association.name].push(removedChildData);
record.setDirty();
}, me);
}
//Only return data if it was dirty, new or marked for deletion.
if (record.dirty | record.phantom | record.get('forDeletion')){
return data;
}
}
});
Note: Following code only works for has many associations. We need to extend this for has one, in case if we want it for has one associations.

An internal error occurred during: “Requesting JavaScript AST from selection”

Sometime eclipse suddenly stops working by throwing following error
'Requesting Javascript AST from Selection' has encountered a problem. An internal error occured during "Requesting Javascript AST from selection"
and throws following error in the console, if you run eclipse through console.

java.lang.OutOfMemoryError: PermGen space 

Eclipse is not suitable for javascript validations. Sometimes it messes up with javascript and throws this error. You can disable javascript validation to get rid-off this error.

  • Go to window-preferences, search for mark
  • Select Javascript - editor - Mark Occurrences
  • Uncheck Mark selected occurrences as shown below
 

Friday, 7 March 2014

Spring xml validation failures in eclipse

While working with spring framework in eclipse, sometimes suddenly xmls fail to validate by throwing following marker error in eclipse.

Multiple markers at this line
    - cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element
     'context:component-scan'.
    - schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/context/spring-
     context.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the
     document is not <xsd:schema>.

   
It could be a problem that spring jars are not accessible in the class path or different version of spring xsd files are cached in eclipse.

More frequently if you go offline, then eclipse starts showing this error(Eventhough if you connect to internet again). You can get rid off this error by clearing cached xsd templates and re-validating them.

Go to eclipse preferences, search for 'cache'(Generally it is under Network Connections), select all xsd files and remove them. After removing xsd files revalidate xmls files.