Tuesday, March 16, 2010

Custom Settings and MIXED_DML_OPERATION

Some folks have noticed an issue when using the new Custom Settings feature in Apex. When you have a piece of code that does DML on both a custom setting and a regular object, you get:

"MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa)"

What is Mixed DML? Well, certain types of DML simply do not mix well. For instance, if you change a Profile and also an Account (in the same transaction), you might be altering the profile in such a way that it no longer has access to that Account. So, there's a certain set of combinations that will yield a MIXED_DML_OPERATION exception.

In general, the way to get around this is to do your second bit of DML in a @Future method, as that will happen in its own transaction (though it's important to note that, in a test method, @Future method invocations are inlined, so you will still get the MIXED_DML_OPERATION exception).

However, starting in version 18.0, Custom Settings are no longer placed in this special bucket. You can now do DML on Custom Setting objects and other (non-setup) objects in the same transaction.

Just be sure your code is set to version 18.0!

Thursday, March 11, 2010

Apex Describes and class versions

I'm resurrecting this blog for posts related to Apex, as using my java.net blog for that purpose would be inappropriate. I'm not sure how often I'll post. When things of general interest crop up while I'm working on the Apex compiler, I suppose.

Today's topic came up as part of a customer support escalation. It's a tricky gotcha with the Apex getMap() function, used for getting all the fields for an sObject type (kind of like reflection for your database objects).

For example, you can get a map of all the fields in the User object by writing:

Map userFields = SObjectType.User.fields.getMap();

With this map, you can see which fields the running user has access to:

boolean b = userFields.get('accountid').getDescribe().isAccessible();

There's a subtle gotcha with using describes, and a fairly simple rule of thumb:

Don't pass the map around between classes.

In my example, I'm getting the AccountId field. This field was added in version 17. Let's say you have two classes, QueryBuilder and DescribeUtil.

// version 16
public class QueryBuilder {
  public String buildQuery {
    Map userFields = DescribeUtil.getUserFields();
    String fieldlist = '';
    for (String key : userFields.keySet()) {
      if (userFields.get(key).getDescribe().isAccessible())
        fieldlist = fieldlist + ',' + key;
    }
  }
}

// version 17
public class DescribeUtil {
  public static Map getUseFields() {
    return SObjectType.User.fields.getMap();
  }
}

You will get an error:

Field User.AccountId is inaccessible in this context

Why? Because QueryBuilder is running in a world where the AccountId field doesn't exist yet! If the getMap() call were done in QueryBuilder, it wouldn't be in there.

So, do yourselves a favor and don't pass these maps around from class to class. The version mismatch is an easy thing to miss.



Wednesday, March 23, 2005

Thursday, February 24, 2005

At the pub with netbeans folks

There are a bunch of sun developers in town for an internal training seminar on netbeans. I'm the only non-Sun employee speaking at this seminar. I'm giving a little talk on the cluster build harness and my Feedreader tutorial (which won the ipod, BTW).

Anyway, last night a bunch of us got together at a pub in Burlingame. I got to meet Sanjeev of the safari netbeans project, a bunch of folks from the Java Studio Creator team, and more Petr's than you can shake a stick at :-)

One thing that really surprised me is the sheer number of developers they have working on netbeans. Between the netbeans core team, the JSC team, and other groups working on netbeans-related technologies, we're talking hundereds. My team has 3.5!

We talked about JDIC in netbeans, mac support (which Tim Boundreau is very keen on, and as of fairly recently, Apple is too), which openapis need to go, and which ones need to be beefed up. It may not always look like it from just reading the mailing lists, but these guys are pretty much on top of what needs to be done, and how to do it.

One of the major hurdles to improving netbeans, I learned, is Sun's legal department, and their attitude towards integrating open source projects. It's not enough for the lawyers to approve, say, the Apache License, and have that be the end of it. NO, they need to go through a month or two of painful wrangling for EACH library, even if they're all covered under the same license! Worse yet, no one knows how to fix this!

Another example: JDIC. It's LGPL, which makes their lawyers tremble. This is not without reason, as there's a valid debate about the LGPL as it applies to class files. However, there are 2 problems with this. Firstly, there's no doubt that the intent of the LGPL as applied to java libraries is to allow developers to drop a jar into the classpath and use it. Secondly, JDIC's copyright is owned by ... Sun! Are they going to sue themselves?!

This kind of insanity could, in my opinion, kill netbeans in the long run. Netbeans can't be slow on the uptake when adopting open source java technologies. They can't be reticent to have good support for JDNC, or struts, or anything else, simply because it's too hard to run through the bureaucracy of putting the library in a module.

It should work the other way, too. Netbeans has had technology like the commons VFS for a long, long time. Why did anyone feel the need to rewrite it?

Tim just wrote a prototype of something he's hoping will replace SystemOption (it's in contrib/options). When I told him there was already a commons library for doing exactly the same thing, he said it was easier to rewrite it than get approval to use the commons library.

WTF?!

Wednesday, January 26, 2005

MultiView

So, I just made my first multiview component. It was easier than I expected, and the source code in the minicomposer example was particularly helpful.

In fact, too helpful. Or, rather, it was so precisely what I needed, that I wonder why it was necessary for me to copy so much source code verbatim, rather than just invoking some higher level API.

If you have a file type that can be edited in 2 ways (text and some other GUI), and you've already written TopComponents for both, you can pretty much just paste in a big chunk of the minicomposer ScoreEditorSupport to your own EditorSupport, and pull in a little code from ScorePanel to your own GUI TopComponent. You may want to change the names of the buttons ("compose", for me, became "graph"). But that's about it.

Extremely simple, but not exactly the best example of code reuse.

Thursday, January 20, 2005

code snippets in blogger.com?

That last post was a pain, to get the whitespace to work. Anyone know of a better way to get spaces or tabs at the beginning of lines, besides inserting a bunch of   tokens?

TopComponentGroup semantics

I've been struggling with TopComponentGroup semantics. Basically, I have a TopComponent class A, and a singleton TopComponent B that displays property sheets relating to A. So, in my window system delcarations, I make a group containing the singleton B.

The trick is, when do I call open() and close() on the TopComponentGroup? The conventional wisdom is to have:

protected void componentActivated() {
 super.componentActivated();
 TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup(TC_GROUP);
 if (group != null) {
  group.open();
 }
}

protected void componentDeactivated() {
 TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup(TC_GROUP);
 if (group != null) {
  group.close();
 }
}
This, however, doesn't work. For one thing, when I click on B, I am deactivating A. Therefore, clicking on B makes it disappear! My next thought was to use componentShowing() and componentHidden() instead of activated/deactivated. But, if I have 2 A's showing in different modes, that paradigm breaks down. Long story short(er), this is what I ended up with, and it seems to work:
protected void componentActivated() {
 super.componentActivated();

 TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup(TC_GROUP);
 if (group != null) {
  group.open();
 }
}

protected void componentHidden() {
 Mode m = WindowManager.getDefault().findMode(this);
 if (m == null) {
  // if the component is hiding because it is being closed,
  // we must back off to assuming the editor mode
  m = WindowManager.getDefault().findMode(EDITOR_MODE);
 }

 TopComponent selected = m.getSelectedTopComponent();
 if (selected == null || !(selected instanceof PageEditor)) {
  // close the TC_GROUP
  TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup(TC_GROUP);
  if (group != null)
   group.close();
 }
}

New NetBeans Platform Tutorial

I've finished my entry for the netbeans tutorial contest. Of course, they then extended the deadline. However, they've allowed me to post it anyway, so folks get get use out of it right away. Check it out at http://www.cs.wustl.edu/~rbu1/feedreader/.

My office-mate has already (correctly) pointed out that there's no reason for SiteListComponent to subclass CloneableTopComponent, as it's a singleton. Oops.

While I was at it, I added an explorer module to the cluster build harness. It was a rush job, but people have been asking for a while for some simple sample code that adds node-exploring capability to the bare platform. Right now, it's just got a hidden root node with children gathered from java.io.File.listRoots().

Hopefully, all this will help some folks get their work done.

...and maybe the tutorial will turn out to be ipod-worthy :)