Tuesday, February 17, 2015

Ran into an interesting JAXB issue. We have several classes that all extends a Base class. At one point I introduced an object property into the base class, that also happened to be a property defined in just ONE of the subclasses. This caused any setter of this property from ANY subclasses (outside the one with that property overridden) to have this property completely ignored in the XML output. Example
@XmlRootElement(name = "animal")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Dog.class, Fish.class})
public class Animal {
    protected String movement;
     ....
}

@XmlRootElement(name = "dog")
@XmlSeeAlso({Animal.class})
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog extends Animal {
   private String breed;
   protected String movement;
   ....
}

@XmlRootElement(name = "fish")
@XmlSeeAlso({Animal.class})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fish extends Animal {
    private String scaleType;
    ....
}

public static void main(String[] args) {
    Dog dog = new Dog();
    dog.setBreed("lab");
    dog.setMovement("walks"); 
    String xml = AnimalJaxb.toXml(dog);
    System.out.println("dog = "+xml);

    Fish fish = new Fish();
    fish.setMovement("swims"); //WILL NOT SHOW UP IN XML!
    fish.setScaleType("normal"); 
    String xml = AnimalJaxb.toXml(fish);
    System.out.println("fish = "+xml); 
When the above runs. The "movement" property on Fish will NOT be in the XML. To fix this, I needed to remove the overridden movement property in the Dog class. What's frustrating is JAXB doesn't throw any errors or complain. The only way it will complain is if I make the base class (Animal) abstract and mark it @XmlTransient, afterwhich JAXB will complain about having "two properties with the same name."

Friday, May 31, 2013

ZK - Paginating Large Results sets in ZK with MyBatis

Benefit of this type of paging is that it doesn't load all the results up front. Useful for very large result sets. I'm a fan of MyBatis, so this example below demonstrates the use with MyBatis.



ZUL


 
 <paging id="executionsPaging"
  onCreate="executionsList.setPaginal(self)"
  totalSize="@bind(vm.executionsTotalSize)"
  pageSize="@bind(vm.executionsPageSize)"
  activePage="@bind(vm.currentPageNumber)"
  onPaging="@command('pageExecutions', pageNum=event.activePage)"
  /> 


 <listbox id="executionsList" model="@load(vm.executions)"
       selectedItem="@bind(vm.selectedExecution)".... />


Executions ViewModel


public class ExecutionsVM {
 private final static Logger logger = LoggerFactory.getLogger(ExecutionsVM.class);

 private List executions = new ArrayList();
 private ExecutionSearchFilter searchFilter = new ExecutionSearchFilter();
 private long executionsTotalSize = 0l;
 private int executionsPageSize = 25;
 private int currentPageNumber = 0;

 @WireVariable
 private ExecutionService executionService;

 @NotifyChange({"executions","executionsTotalSize"})
 @Command
 public void pageExecutions(@BindingParam("pageNum") int pageNum) {
  logger.debug("pageExecutions for pagNum {}", pageNum);
  this.currentPageNumber = pageNum;
  populateSearchFilter();
  executions = executionService.getExecutions(searchFilter);
  executionsTotalSize = executionService.getExecutionsSize(searchFilter);
 }

 private void populateSearchFilter() {
  int base = this.currentPageNumber * executionsPageSize;
  int firstRow = base + 1;
  int lastRow = base + executionsPageSize;
  searchFilter.setLowerRowLimit(firstRow);
  searchFilter.setUpperRowLimit(lastRow);
 }

}

Executions Service (wraps Mapper)


@Service
public class ExecutionService {

 @Resource
 private ExecutionMapper executionMapper;

 public List featchExecutions(ExecutionSearchFilter searchFilter) {
  return executionMapper.getExecutions(searchFilter);
 }
}

Executions Mapper


public interface ExecutionMapper {
 List featchExecutions(ExecutionSearchFilter searchFilter) 
}

Search Filter POJO


public class ExecutionSearchFilter {
 private int upperRowLimit;
 private int lowerRowLimit;
    //setters/getters
}

Executions Mapper MXL


<select id="getExecutions" resultMap="executionResultMap" parameterType="ExecutionSearchFilter">
  select
   EXECUTION_ID,
   EXECUTION_NM,
   ROW_NUM
  FROM
   (
    SELECT
     tempRow.EXECUTION_ID,
     tempRow.EXECUTION_NM,
     rownum ROW_NUM
    from
    (
     SELECT
      e.EXECUTION_ID,
      e.EXECUTION_NM
     FROM
      EXECUTION_T e
    ) tempRow
    WHERE
     rownum <![CDATA[ <= ]]> #{upperRowLimit}
   )
  WHERE
   ROW_NUM >= #{lowerRowLimit}
</select>

Friday, May 24, 2013

ZK Tips

Figured I'd list some of the tips here as I work with ZK. A lot of things aren't immediately apparent even using the online docs.

NotifyChange from your Base ViewModels


In annoying thing in ZK is that if your ViewModel extends another ViewModel and your base ViewModel decides that it needs to delegate a call to its subclass, the subclass @NotifyChange({"props}") will not automatically be triggered. As an example take:
public abstract class BaseVM {

 public void doSomething() {
  //do Stuff
  //delegate to implementing class
  doSomeStuff();
 }
 public abstract void doSomeStuff();
}

public ChildVM extends BaseVM {
 private String someProperty;

 @NotifyChange("someProperty")
 public void doSomeStuff() {
  someProperty = "blah";
 }

 public String getSomeProperty() {
  return someProperty;
    }
}
It would be nice if when "doSomeStuff" is called that "someProperty" would be able to be notified so it could display properly in your zul. Matze2 on the forums helped provide the work around http://forum.zkoss.org/question/86637/notifychange-in-subclass-methods-called-from-parent-will-not-fire/ Solution is to use the "Binder" object. Illustrated as so...
public abstract class BaseVM {
 
 protected Binder binder;

 @Init
 public final void init(@ContextParam(ContextType.BINDER) Binder _binder) {
  binder = _binder;
 }

 public void doSomething() {
  //do Stuff
  //delegate to implementing class
  doSomeStuff();
  binder.notifyChange(this, "someProperty");
 }
 public abstract void doSomeStuff();
}

public ChildVM extends BaseVM {
 private String someProperty;

 @Init(superclass=true)
 public void init() {
 }

 @NotifyChange("someProperty")
 public void doSomeStuff() {
  someProperty = "blah";
 }

 public String getSomeProperty() {
  return someProperty;
    }
}
Don't forget the @Init(superclass=true) in your subclass (I think you can add it to the Class annotation if you aren't providing an init method in your subclass.) The above is clunky but it works.

Use Constants for your GlobalCommands


Most of the documentation and examples demonstrate declaring GlobalCommmand annotations like:
@GlobalCommand
public void someMethod() { ... }
and calling it from some other ViewModel like so:
BindUtils.postGlobalCommand(null, null, "someMethod", null);
The problem with this is it's extremely fragile. If you decide to refactor your method name, you end up then having to do a search and replace for everywhere you've called your Global command with "someMethod." Possibly more annoying is you do not get any IDE help when you want to post to this GlobalCommand from another ViewModel... you need to recall the exact name of the method and if you can't recall the name you have to remember where that GlobalCommand was defined which could take time in a large project. Instead, I recommend always getting in the habit of using a GlobalCommandValues class that declares the GlobalCommand as String constant and then using it in your annotation and of course in your postGlobalCommand calls. This seems obvious, but I wasn't even aware it was an option.
//GlobalCommandValues class
public static final String SOME_METHOD = "someMethod";

//ViewModel
@GlobalCommand(GlobalCommandValues.SOME_METHOD)
public void someMethodDoesntHaveToMatchYourConstant() { ... }

//Usage
BindUtils.postGlobalCommand(null, null, GlobalCommandValues.SOME_METHOD, null);

Tuesday, June 26, 2012

EL in ZK 6 I had some issues trying to figure out some basic stuff since I didn't see it documented anywhere.

For concatenation I seemed to have to use el2's concat function...



 

For equals you can't use == , need to use el's 'eq' or 'ne'
visible="@load(productGroup.owner.id eq user.id)" 

Monday, April 2, 2012

Groovy - using a writer with FileIO

Groovy - using a writer with FileIO


public void writeToFile(def directory, def fileName, def extension, def infoList) {
new File("$directory/$fileName$extension").withWriter { out ->
infoList.each {
out.println it
}
}
}

Wednesday, May 4, 2011

Note Taking on the Mac/IPhone/etc

In another post I commented about Notaional Velocity and SimpleNote. I still use that as my primary note taking combination for simple things that I'll often want to look up quickly - eg Last oil changes, printer cartridge type, size of the AC filter, list of names of people I meet, list of movies to check out, etc Basically I'm using Simplenote (Notaional Velocity on Mac that syncs to Simplenote) for anything I'd want quickly on my iPhone as well.

For work stuff - tasks, project notes, developer code snippets etc. I'm using MacJournal. I toyed around with using Evernote but I didn't like it for work notes. The main reasons I didn't like Evernote is

1) You can't reorganize your notes in a predefined order. They're argument is 'use the search feature.' And I agree for simple notes that's fine. But for work I often keep a list of notes that I have neatly organized with a few things at the top such as "server names" "common commands" etc. With MacJournalI can always keep them at the top. With Evernote you can't.

2) They don't have the nice split vertical pane that MacJournal has. They have it - but it defaults to a view that has icons in it and it's just a waste of space. They do have a flat list view but it splits it horizontally which still isn't what I want.

3) Evernote now does support nested folders, but it's still sort of goofy (if you drag a folder onto another you'd expect it to immediately just become a subfolder - but that's not what happens.) MacJournal makes it intuitive with nested journals.

Thursday, March 4, 2010

National Velocity plus Simplenote

I’m really digging this combo for note taking on my Mac and iPhone. I was using Evernote, but it’s a bit heavy and I only seem to be keeping text notes.

National Velocity (I know goofy name and the website is lacking) is a nice light weight note taking app for the Mac. I was using Mori, which I liked but they currently have no way to sync to my iPhone. National Velocity will synch with Simplenote which is a really nice note taking application for the iPhone (free.) Simplenote has a nice web client as well (which is what National Velocity syncs with behind the scenes.)

Blogger Syntax Highliter