Merge branch '2.5'
diff --git a/release-notes/VERSION b/release-notes/VERSION
index adc94b5..850bbb3 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -18,6 +18,8 @@
  (reported by Antibrumm@github)
 #703: Multiple calls to ObjectMapper#canSerialize(Object.class) returns different values
  (reported by flexfrank@github)
+#705: JsonAnyGetter doesn't work with JsonSerialize (except with keyUsing)
+ (reported by natnan@github)
 
 2.5.1 (06-Feb-2015)
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java b/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
index 3bfa7b2..9fe4077 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/AnyGetterWriter.java
@@ -20,18 +20,24 @@
      * Method (or field) that represents the "any getter"
      */
     protected final AnnotatedMember _accessor;
+
+    protected JsonSerializer<Object> _serializer;
+
+    protected MapSerializer _mapSerializer;
     
-    protected MapSerializer _serializer;
-    
+    @SuppressWarnings("unchecked")
     public AnyGetterWriter(BeanProperty property,
-            AnnotatedMember accessor, MapSerializer serializer)
+            AnnotatedMember accessor, JsonSerializer<?> serializer)
     {
         _accessor = accessor;
         _property = property;
-        _serializer = serializer;
+        _serializer = (JsonSerializer<Object>) serializer;
+        if (serializer instanceof MapSerializer) {
+            _mapSerializer = (MapSerializer) serializer;
+        }
     }
 
-    public void getAndSerialize(Object bean, JsonGenerator jgen, SerializerProvider provider)
+    public void getAndSerialize(Object bean, JsonGenerator gen, SerializerProvider provider)
         throws Exception
     {
         Object value = _accessor.getValue(bean);
@@ -42,32 +48,49 @@
             throw new JsonMappingException("Value returned by 'any-getter' ("
                     +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
         }
-        _serializer.serializeFields((Map<?,?>) value, jgen, provider);
+        // 23-Feb-2015, tatu: Nasty, but has to do (for now)
+        if (_mapSerializer != null) {
+            _mapSerializer.serializeFields((Map<?,?>) value, gen, provider);
+            return;
+        }
+        _serializer.serialize(value, gen, provider);
     }
 
     /**
      * @since 2.3
      */
-    public void getAndFilter(Object bean, JsonGenerator jgen, SerializerProvider provider,
+    public void getAndFilter(Object bean, JsonGenerator gen, SerializerProvider provider,
             PropertyFilter filter)
-        throws Exception
-        {
-            Object value = _accessor.getValue(bean);
-            if (value == null) {
-                return;
-            }
-            if (!(value instanceof Map<?,?>)) {
-                throw new JsonMappingException("Value returned by 'any-getter' ("
-                        +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
-            }
-            // 19-Oct-2014, tatu: Should we try to support @JsonInclude options here?
-            _serializer.serializeFilteredFields((Map<?,?>) value, jgen, provider, filter, null);
+                    throws Exception
+    {
+        Object value = _accessor.getValue(bean);
+        if (value == null) {
+            return;
         }
+        if (!(value instanceof Map<?,?>)) {
+            throw new JsonMappingException("Value returned by 'any-getter' ("
+                    +_accessor.getName()+"()) not java.util.Map but "+value.getClass().getName());
+        }
+        // 19-Oct-2014, tatu: Should we try to support @JsonInclude options here?
+        if (_mapSerializer != null) {
+            _mapSerializer.serializeFilteredFields((Map<?,?>) value, gen, provider, filter, null);
+            return;
+        }
+        // ... not sure how custom handler would do it
+        _serializer.serialize(value, gen, provider);
+    }
     
     // Note: NOT part of ResolvableSerializer...
+    @SuppressWarnings("unchecked")
     public void resolve(SerializerProvider provider) throws JsonMappingException
     {
         // 05-Sep-2013, tatu: I _think_ this can be considered a primary property...
-        _serializer = (MapSerializer) provider.handlePrimaryContextualization(_serializer, _property);
+        if (_serializer instanceof ContextualSerializer) {
+            JsonSerializer<?> ser = provider.handlePrimaryContextualization(_serializer, _property);
+            _serializer = (JsonSerializer<Object>) ser;
+            if (ser instanceof MapSerializer) {
+                _mapSerializer = (MapSerializer) ser;
+            }
+        }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
index 7049d59..83e7373 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
@@ -391,18 +391,22 @@
             JavaType valueType = type.getContentType();
             TypeSerializer typeSer = createTypeSerializer(config, valueType);
             // last 2 nulls; don't know key, value serializers (yet)
-            // TODO: support '@JsonIgnoreProperties' with any setter?
-            MapSerializer mapSer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
-                    typeSer, null, null, /*filterId*/ null);
+            // 23-Feb-2015, tatu: As per [#705], need to support custom serializers
+            JsonSerializer<?> anySer = findSerializerFromAnnotation(prov, anyGetter);
+            if (anySer == null) {
+                // TODO: support '@JsonIgnoreProperties' with any setter?
+                anySer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
+                        typeSer, null, null, /*filterId*/ null);
+            }
             // TODO: can we find full PropertyName?
             PropertyName name = PropertyName.construct(anyGetter.getName());
             BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null,
                     beanDesc.getClassAnnotations(), anyGetter, PropertyMetadata.STD_OPTIONAL);
-            builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, mapSer));
+            builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, anySer));
         }
         // Next: need to gather view information, if any:
         processViews(config, builder);
-        
+
         // Finally: let interested parties mess with the result bit more...
         if (_factoryConfig.hasSerializerModifiers()) {
             for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.orig b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.orig
new file mode 100644
index 0000000..1712a1a
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.orig
@@ -0,0 +1,735 @@
+package com.fasterxml.jackson.databind.ser;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.ObjectIdGenerator;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
+import com.fasterxml.jackson.databind.introspect.*;
+import com.fasterxml.jackson.databind.jsontype.NamedType;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter;
+import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
+import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator;
+import com.fasterxml.jackson.databind.ser.std.MapSerializer;
+import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer;
+import com.fasterxml.jackson.databind.type.*;
+import com.fasterxml.jackson.databind.util.ArrayBuilders;
+import com.fasterxml.jackson.databind.util.ClassUtil;
+import com.fasterxml.jackson.databind.util.Converter;
+
+/**
+ * Factory class that can provide serializers for any regular Java beans
+ * (as defined by "having at least one get method recognizable as bean
+ * accessor" -- where {@link Object#getClass} does not count);
+ * as well as for "standard" JDK types. Latter is achieved
+ * by delegating calls to {@link BasicSerializerFactory} 
+ * to find serializers both for "standard" JDK types (and in some cases,
+ * sub-classes as is the case for collection classes like
+ * {@link java.util.List}s and {@link java.util.Map}s) and bean (value)
+ * classes.
+ *<p>
+ * Note about delegating calls to {@link BasicSerializerFactory}:
+ * although it would be nicer to use linear delegation
+ * for construction (to essentially dispatch all calls first to the
+ * underlying {@link BasicSerializerFactory}; or alternatively after
+ * failing to provide bean-based serializer}, there is a problem:
+ * priority levels for detecting standard types are mixed. That is,
+ * we want to check if a type is a bean after some of "standard" JDK
+ * types, but before the rest.
+ * As a result, "mixed" delegation used, and calls are NOT done using
+ * regular {@link SerializerFactory} interface but rather via
+ * direct calls to {@link BasicSerializerFactory}.
+ *<p>
+ * Finally, since all caching is handled by the serializer provider
+ * (not factory) and there is no configurability, this
+ * factory is stateless.
+ * This means that a global singleton instance can be used.
+ */
+public class BeanSerializerFactory
+    extends BasicSerializerFactory
+    implements java.io.Serializable // since 2.1
+{
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Like {@link BasicSerializerFactory}, this factory is stateless, and
+     * thus a single shared global (== singleton) instance can be used
+     * without thread-safety issues.
+     */
+    public final static BeanSerializerFactory instance = new BeanSerializerFactory(null);
+
+    /*
+    /**********************************************************
+    /* Life-cycle: creation, configuration
+    /**********************************************************
+     */
+
+    /**
+     * Constructor for creating instances with specified configuration.
+     */
+    protected BeanSerializerFactory(SerializerFactoryConfig config)
+    {
+        super(config);
+    }
+    
+    /**
+     * Method used by module registration functionality, to attach additional
+     * serializer providers into this serializer factory. This is typically
+     * handled by constructing a new instance with additional serializers,
+     * to ensure thread-safe access.
+     */
+    @Override
+    public SerializerFactory withConfig(SerializerFactoryConfig config)
+    {
+        if (_factoryConfig == config) {
+            return this;
+        }
+        /* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor;
+         *    and we pretty much have to here either choose between losing subtype instance
+         *    when registering additional serializers, or losing serializers.
+         *    Instead, let's actually just throw an error if this method is called when subtype
+         *    has not properly overridden this method; this to indicate problem as soon as possible.
+         */
+        if (getClass() != BeanSerializerFactory.class) {
+            throw new IllegalStateException("Subtype of BeanSerializerFactory ("+getClass().getName()
+                    +") has not properly overridden method 'withAdditionalSerializers': can not instantiate subtype with "
+                    +"additional serializer definitions");
+        }
+        return new BeanSerializerFactory(config);
+    }
+
+    @Override
+    protected Iterable<Serializers> customSerializers() {
+        return _factoryConfig.serializers();
+    }
+    
+    /*
+    /**********************************************************
+    /* SerializerFactory impl
+    /**********************************************************
+     */
+
+    /**
+     * Main serializer constructor method. We will have to be careful
+     * with respect to ordering of various method calls: essentially
+     * we want to reliably figure out which classes are standard types,
+     * and which are beans. The problem is that some bean Classes may
+     * implement standard interfaces (say, {@link java.lang.Iterable}.
+     *<p>
+     * Note: sub-classes may choose to complete replace implementation,
+     * if they want to alter priority of serializer lookups.
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public JsonSerializer<Object> createSerializer(SerializerProvider prov,
+            JavaType origType)
+        throws JsonMappingException
+    {
+        // Very first thing, let's check if there is explicit serializer annotation:
+        final SerializationConfig config = prov.getConfig();
+        BeanDescription beanDesc = config.introspect(origType);
+        JsonSerializer<?> ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
+        if (ser != null) {
+            return (JsonSerializer<Object>) ser;
+        }
+        boolean staticTyping;
+        // Next: we may have annotations that further define types to use...
+        JavaType type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), origType);
+        if (type == origType) { // no changes, won't force static typing
+            staticTyping = false;
+        } else { // changes; assume static typing; plus, need to re-introspect if class differs
+            staticTyping = true;
+            if (!type.hasRawClass(origType.getRawClass())) {
+                beanDesc = config.introspect(type);
+            }
+        }
+        // Slight detour: do we have a Converter to consider?
+        Converter<Object,Object> conv = beanDesc.findSerializationConverter();
+        if (conv == null) { // no, simple
+            return (JsonSerializer<Object>) _createSerializer2(prov, type, beanDesc, staticTyping);
+        }
+        JavaType delegateType = conv.getOutputType(prov.getTypeFactory());
+        
+        // One more twist, as per [Issue#288]; probably need to get new BeanDesc
+        if (!delegateType.hasRawClass(type.getRawClass())) {
+            beanDesc = config.introspect(delegateType);
+            // [#359]: explicitly check (again) for @JsonSerializer...
+            ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
+        }
+        if (ser == null) {
+            ser = _createSerializer2(prov, delegateType, beanDesc, true);
+        }
+        return new StdDelegatingSerializer(conv, delegateType, ser);
+    }
+
+    protected JsonSerializer<?> _createSerializer2(SerializerProvider prov,
+            JavaType type, BeanDescription beanDesc, boolean staticTyping)
+        throws JsonMappingException
+    {
+        // Then JsonSerializable, @JsonValue etc:
+        JsonSerializer<?> ser = findSerializerByAnnotations(prov, type, beanDesc);
+        if (ser != null) {
+            return ser;
+        }
+        final SerializationConfig config = prov.getConfig();
+        
+        // Container types differ from non-container types
+        // (note: called method checks for module-provided serializers)
+        if (type.isContainerType()) {
+            if (!staticTyping) {
+                staticTyping = usesStaticTyping(config, beanDesc, null);
+                // [Issue#23]: Need to figure out how to force passed parameterization
+                //  to stick...
+                /*
+                if (property == null) {
+                    JavaType t = origType.getContentType();
+                    if (t != null && !t.hasRawClass(Object.class)) {
+                        staticTyping = true;
+                    }
+                }
+                */
+            }
+            // 03-Aug-2012, tatu: As per [Issue#40], may require POJO serializer...
+            ser =  buildContainerSerializer(prov, type, beanDesc, staticTyping);
+            // Will return right away, since called method does post-processing:
+            if (ser != null) {
+                return ser;
+            }
+        } else {
+            // Modules may provide serializers of POJO types:
+            for (Serializers serializers : customSerializers()) {
+                ser = serializers.findSerializer(config, type, beanDesc);
+                if (ser != null) {
+                    break;
+                }
+            }
+        }
+        
+        // Otherwise, we will check "primary types"; both marker types that
+        // indicate specific handling (JsonSerializable), or main types that have
+        // precedence over container types
+        if (ser == null) {
+            ser = findSerializerByLookup(type, config, beanDesc, staticTyping);
+            if (ser == null) {
+                ser = findSerializerByPrimaryType(prov, type, beanDesc, staticTyping);
+                if (ser == null) {
+                    // And this is where this class comes in: if type is not a
+                    // known "primary JDK type", perhaps it's a bean? We can still
+                    // get a null, if we can't find a single suitable bean property.
+                    ser = findBeanSerializer(prov, type, beanDesc);
+                    // Finally: maybe we can still deal with it as an implementation of some basic JDK interface?
+                    if (ser == null) {
+                        ser = findSerializerByAddonType(config, type, beanDesc, staticTyping);
+                        // 18-Sep-2014, tatu: Actually, as per [jackson-databind#539], need to get
+                        //   'unknown' serializer assigned earlier, here, so that it gets properly
+                        //   post-processed
+                        if (ser == null) {
+                            ser = prov.getUnknownTypeSerializer(beanDesc.getBeanClass());
+                        }
+                    }
+                }
+            }
+        }
+        if (ser != null) {
+            // [Issue#120]: Allow post-processing
+            if (_factoryConfig.hasSerializerModifiers()) {
+                for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
+                    ser = mod.modifySerializer(config, beanDesc, ser);
+                }
+            }
+        }
+        return ser;
+    }
+    
+    /*
+    /**********************************************************
+    /* Other public methods that are not part of
+    /* JsonSerializerFactory API
+    /**********************************************************
+     */
+
+    /**
+     * Method that will try to construct a {@link BeanSerializer} for
+     * given class. Returns null if no properties are found.
+     */
+    public JsonSerializer<Object> findBeanSerializer(SerializerProvider prov, JavaType type, BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        // First things first: we know some types are not beans...
+        if (!isPotentialBeanType(type.getRawClass())) {
+            // 03-Aug-2012, tatu: Except we do need to allow serializers for Enums,
+            //   as per [Issue#24]
+            if (!type.isEnumType()) {
+                return null;
+            }
+        }
+        return constructBeanSerializer(prov, beanDesc);
+    }
+
+    /**
+     * Method called to create a type information serializer for values of given
+     * non-container property
+     * if one is needed. If not needed (no polymorphic handling configured), should
+     * return null.
+     *
+     * @param baseType Declared type to use as the base type for type information serializer
+     * 
+     * @return Type serializer to use for property values, if one is needed; null if not.
+     */
+    public TypeSerializer findPropertyTypeSerializer(JavaType baseType,
+            SerializationConfig config, AnnotatedMember accessor)
+        throws JsonMappingException
+    {
+        AnnotationIntrospector ai = config.getAnnotationIntrospector();
+        TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, accessor, baseType);        
+        // Defaulting: if no annotations on member, check value class
+        if (b == null) {
+            return createTypeSerializer(config, baseType);
+        }
+        Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(
+                accessor, config, ai, baseType);
+        return b.buildTypeSerializer(config, baseType, subtypes);
+    }
+
+    /**
+     * Method called to create a type information serializer for values of given
+     * container property
+     * if one is needed. If not needed (no polymorphic handling configured), should
+     * return null.
+     *
+     * @param containerType Declared type of the container to use as the base type for type information serializer
+     * 
+     * @return Type serializer to use for property value contents, if one is needed; null if not.
+     */    
+    public TypeSerializer findPropertyContentTypeSerializer(JavaType containerType,
+            SerializationConfig config, AnnotatedMember accessor)
+        throws JsonMappingException
+    {
+        JavaType contentType = containerType.getContentType();
+        AnnotationIntrospector ai = config.getAnnotationIntrospector();
+        TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, accessor, containerType);        
+        // Defaulting: if no annotations on member, check value class
+        if (b == null) {
+            return createTypeSerializer(config, contentType);
+        }
+        Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(accessor,
+                config, ai, contentType);
+        return b.buildTypeSerializer(config, contentType, subtypes);
+    }
+    
+    /*
+    /**********************************************************
+    /* Overridable non-public factory methods
+    /**********************************************************
+     */
+
+    /**
+     * Method called to construct serializer for serializing specified bean type.
+     * 
+     * @since 2.1
+     */
+    @SuppressWarnings("unchecked")
+    protected JsonSerializer<Object> constructBeanSerializer(SerializerProvider prov,
+            BeanDescription beanDesc)
+        throws JsonMappingException
+    {
+        // 13-Oct-2010, tatu: quick sanity check: never try to create bean serializer for plain Object
+        // 05-Jul-2012, tatu: ... but we should be able to just return "unknown type" serializer, right?
+        if (beanDesc.getBeanClass() == Object.class) {
+            return prov.getUnknownTypeSerializer(Object.class);
+//            throw new IllegalArgumentException("Can not create bean serializer for Object.class");
+        }
+        final SerializationConfig config = prov.getConfig();
+        BeanSerializerBuilder builder = constructBeanSerializerBuilder(beanDesc);
+        builder.setConfig(config);
+
+        // First: any detectable (auto-detect, annotations) properties to serialize?
+        List<BeanPropertyWriter> props = findBeanProperties(prov, beanDesc, builder);
+        if (props == null) {
+            props = new ArrayList<BeanPropertyWriter>();
+        }
+        // [databind#638]: Allow injection of "virtual" properties:
+        prov.getAnnotationIntrospector().findAndAddVirtualProperties(config, beanDesc.getClassInfo(), props);
+
+        // [JACKSON-440] Need to allow modification bean properties to serialize:
+        if (_factoryConfig.hasSerializerModifiers()) {
+            for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
+                props = mod.changeProperties(config, beanDesc, props);
+            }
+        }
+
+        // Any properties to suppress?
+        props = filterBeanProperties(config, beanDesc, props);
+
+        // [JACKSON-440] Need to allow reordering of properties to serialize
+        if (_factoryConfig.hasSerializerModifiers()) {
+            for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
+                props = mod.orderProperties(config, beanDesc, props);
+            }
+        }
+
+        /* And if Object Id is needed, some preparation for that as well: better
+         * do before view handling, mostly for the custom id case which needs
+         * access to a property
+         */
+        builder.setObjectIdWriter(constructObjectIdHandler(prov, beanDesc, props));
+        
+        builder.setProperties(props);
+        builder.setFilterId(findFilterId(config, beanDesc));
+        
+        AnnotatedMember anyGetter = beanDesc.findAnyGetter();
+        if (anyGetter != null) {
+            if (config.canOverrideAccessModifiers()) {
+                anyGetter.fixAccess();
+            }
+            JavaType type = anyGetter.getType(beanDesc.bindingsForBeanType());
+            // copied from BasicSerializerFactory.buildMapSerializer():
+            boolean staticTyping = config.isEnabled(MapperFeature.USE_STATIC_TYPING);
+            JavaType valueType = type.getContentType();
+            TypeSerializer typeSer = createTypeSerializer(config, valueType);
+            // last 2 nulls; don't know key, value serializers (yet)
+            // TODO: support '@JsonIgnoreProperties' with any setter?
+            MapSerializer mapSer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
+                    typeSer, null, null, /*filterId*/ null);
+            // TODO: can we find full PropertyName?
+            PropertyName name = new PropertyName(anyGetter.getName());
+            BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null,
+                    beanDesc.getClassAnnotations(), anyGetter, PropertyMetadata.STD_OPTIONAL);
+            builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, mapSer));
+        }
+        // Next: need to gather view information, if any:
+        processViews(config, builder);
+        
+        // Finally: let interested parties mess with the result bit more...
+        if (_factoryConfig.hasSerializerModifiers()) {
+            for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) {
+                builder = mod.updateBuilder(config, beanDesc, builder);
+            }
+        }
+        
+        JsonSerializer<Object> ser = (JsonSerializer<Object>) builder.build();
+        
+        if (ser == null) {
+            // If we get this far, there were no properties found, so no regular BeanSerializer
+            // would be constructed. But, couple of exceptions.
+            // First: if there are known annotations, just create 'empty bean' serializer
+            if (beanDesc.hasKnownClassAnnotations()) {
+                return builder.createDummy();
+            }
+        }
+        return ser;
+    }
+
+    protected ObjectIdWriter constructObjectIdHandler(SerializerProvider prov,
+            BeanDescription beanDesc, List<BeanPropertyWriter> props)
+        throws JsonMappingException
+    {
+        ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo();
+        if (objectIdInfo == null) {
+            return null;
+        }
+        ObjectIdGenerator<?> gen;
+        Class<?> implClass = objectIdInfo.getGeneratorType();
+
+        // Just one special case: Property-based generator is trickier
+        if (implClass == ObjectIdGenerators.PropertyGenerator.class) { // most special one, needs extra work
+            String propName = objectIdInfo.getPropertyName().getSimpleName();
+            BeanPropertyWriter idProp = null;
+
+            for (int i = 0, len = props.size() ;; ++i) {
+                if (i == len) {
+                    throw new IllegalArgumentException("Invalid Object Id definition for "+beanDesc.getBeanClass().getName()
+                            +": can not find property with name '"+propName+"'");
+                }
+                BeanPropertyWriter prop = props.get(i);
+                if (propName.equals(prop.getName())) {
+                    idProp = prop;
+                    /* Let's force it to be the first property to output
+                     * (although it may still get rearranged etc)
+                     */
+                    if (i > 0) {
+                        props.remove(i);
+                        props.add(0, idProp);
+                    }
+                    break;
+                }
+            }
+            JavaType idType = idProp.getType();
+            gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp);
+            // one more thing: must ensure that ObjectIdWriter does not actually write the value:
+            return ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId());
+            
+        } 
+        // other types are simpler
+        JavaType type = prov.constructType(implClass);
+        // Could require type to be passed explicitly, but we should be able to find it too:
+        JavaType idType = prov.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
+        gen = prov.objectIdGeneratorInstance(beanDesc.getClassInfo(), objectIdInfo);
+        return ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen,
+                objectIdInfo.getAlwaysAsId());
+    }
+
+    /**
+     * Method called to construct a filtered writer, for given view
+     * definitions. Default implementation constructs filter that checks
+     * active view type to views property is to be included in.
+     */
+    protected BeanPropertyWriter constructFilteredBeanWriter(BeanPropertyWriter writer,
+            Class<?>[] inViews)
+    {
+        return FilteredBeanPropertyWriter.constructViewBased(writer, inViews);
+    }
+    
+    protected PropertyBuilder constructPropertyBuilder(SerializationConfig config,
+            BeanDescription beanDesc)
+    {
+        return new PropertyBuilder(config, beanDesc);
+    }
+
+    protected BeanSerializerBuilder constructBeanSerializerBuilder(BeanDescription beanDesc) {
+        return new BeanSerializerBuilder(beanDesc);
+    }
+    
+    /*
+    /**********************************************************
+    /* Overridable non-public introspection methods
+    /**********************************************************
+     */
+    
+    /**
+     * Helper method used to skip processing for types that we know
+     * can not be (i.e. are never consider to be) beans: 
+     * things like primitives, Arrays, Enums, and proxy types.
+     *<p>
+     * Note that usually we shouldn't really be getting these sort of
+     * types anyway; but better safe than sorry.
+     */
+    protected boolean isPotentialBeanType(Class<?> type)
+    {
+        return (ClassUtil.canBeABeanType(type) == null) && !ClassUtil.isProxyType(type);
+    }
+
+    /**
+     * Method used to collect all actual serializable properties.
+     * Can be overridden to implement custom detection schemes.
+     */
+    protected List<BeanPropertyWriter> findBeanProperties(SerializerProvider prov,
+            BeanDescription beanDesc, BeanSerializerBuilder builder)
+        throws JsonMappingException
+    {
+        List<BeanPropertyDefinition> properties = beanDesc.findProperties();
+        final SerializationConfig config = prov.getConfig();
+
+        // [JACKSON-429]: ignore specified types
+        removeIgnorableTypes(config, beanDesc, properties);
+        
+        // and possibly remove ones without matching mutator...
+        if (config.isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)) {
+            removeSetterlessGetters(config, beanDesc, properties);
+        }
+        
+        // nothing? can't proceed (caller may or may not throw an exception)
+        if (properties.isEmpty()) {
+            return null;
+        }
+        // null is for value type serializer, which we don't have access to from here (ditto for bean prop)
+        boolean staticTyping = usesStaticTyping(config, beanDesc, null);
+        PropertyBuilder pb = constructPropertyBuilder(config, beanDesc);
+        
+        ArrayList<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>(properties.size());
+        TypeBindings typeBind = beanDesc.bindingsForBeanType();
+        for (BeanPropertyDefinition property : properties) {
+            final AnnotatedMember accessor = property.getAccessor();
+            // [JACKSON-762]: type id? Requires special handling:
+            if (property.isTypeId()) {
+                if (accessor != null) { // only add if we can access... but otherwise?
+                    if (config.canOverrideAccessModifiers()) {
+                        accessor.fixAccess();
+                    }
+                    builder.setTypeId(accessor);
+                }
+                continue;
+            }
+            // [JACKSON-235]: suppress writing of back references
+            AnnotationIntrospector.ReferenceProperty refType = property.findReferenceType();
+            if (refType != null && refType.isBackReference()) {
+                continue;
+            }
+            if (accessor instanceof AnnotatedMethod) {
+                result.add(_constructWriter(prov, property, typeBind, pb, staticTyping, (AnnotatedMethod) accessor));
+            } else {
+                result.add(_constructWriter(prov, property, typeBind, pb, staticTyping, (AnnotatedField) accessor));
+            }
+        }
+        return result;
+    }
+
+    /*
+    /**********************************************************
+    /* Overridable non-public methods for manipulating bean properties
+    /**********************************************************
+     */
+    
+    /**
+     * Overridable method that can filter out properties. Default implementation
+     * checks annotations class may have.
+     */
+    protected List<BeanPropertyWriter> filterBeanProperties(SerializationConfig config,
+            BeanDescription beanDesc, List<BeanPropertyWriter> props)
+    {
+        AnnotationIntrospector intr = config.getAnnotationIntrospector();
+        AnnotatedClass ac = beanDesc.getClassInfo();
+        String[] ignored = intr.findPropertiesToIgnore(ac);
+        if (ignored != null && ignored.length > 0) {
+            HashSet<String> ignoredSet = ArrayBuilders.arrayToSet(ignored);
+            Iterator<BeanPropertyWriter> it = props.iterator();
+            while (it.hasNext()) {
+                if (ignoredSet.contains(it.next().getName())) {
+                    it.remove();
+                }
+            }
+        }
+        return props;
+    }
+
+    /**
+     * Method called to handle view information for constructed serializer,
+     * based on bean property writers.
+     *<p>
+     * Note that this method is designed to be overridden by sub-classes
+     * if they want to provide custom view handling. As such it is not
+     * considered an internal implementation detail, and will be supported
+     * as part of API going forward.
+     */
+    protected void processViews(SerializationConfig config, BeanSerializerBuilder builder)
+    {
+        // [JACKSON-232]: whether non-annotated fields are included by default or not is configurable
+        List<BeanPropertyWriter> props = builder.getProperties();
+        boolean includeByDefault = config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
+        final int propCount = props.size();
+        int viewsFound = 0;
+        BeanPropertyWriter[] filtered = new BeanPropertyWriter[propCount];
+        // Simple: view information is stored within individual writers, need to combine:
+        for (int i = 0; i < propCount; ++i) {
+            BeanPropertyWriter bpw = props.get(i);
+            Class<?>[] views = bpw.getViews();
+            if (views == null) { // no view info? include or exclude by default?
+                if (includeByDefault) {
+                    filtered[i] = bpw;
+                }
+            } else {
+                ++viewsFound;
+                filtered[i] = constructFilteredBeanWriter(bpw, views);
+            }
+        }
+        // minor optimization: if no view info, include-by-default, can leave out filtering info altogether:
+        if (includeByDefault && viewsFound == 0) {
+            return;
+        }
+        builder.setFilteredProperties(filtered);
+    }
+
+    /**
+     * Method that will apply by-type limitations (as per [JACKSON-429]);
+     * by default this is based on {@link com.fasterxml.jackson.annotation.JsonIgnoreType}
+     * annotation but can be supplied by module-provided introspectors too.
+     */
+    protected void removeIgnorableTypes(SerializationConfig config, BeanDescription beanDesc,
+            List<BeanPropertyDefinition> properties)
+    {
+        AnnotationIntrospector intr = config.getAnnotationIntrospector();
+        HashMap<Class<?>,Boolean> ignores = new HashMap<Class<?>,Boolean>();
+        Iterator<BeanPropertyDefinition> it = properties.iterator();
+        while (it.hasNext()) {
+            BeanPropertyDefinition property = it.next();
+            AnnotatedMember accessor = property.getAccessor();
+            if (accessor == null) {
+                it.remove();
+                continue;
+            }
+            Class<?> type = accessor.getRawType();
+            Boolean result = ignores.get(type);
+            if (result == null) {
+                BeanDescription desc = config.introspectClassAnnotations(type);
+                AnnotatedClass ac = desc.getClassInfo();
+                result = intr.isIgnorableType(ac);
+                // default to false, non-ignorable
+                if (result == null) {
+                    result = Boolean.FALSE;
+                }
+                ignores.put(type, result);
+            }
+            // lotsa work, and yes, it is ignorable type, so:
+            if (result.booleanValue()) {
+                it.remove();
+            }
+        }
+    }
+
+    /**
+     * Helper method that will remove all properties that do not have a mutator.
+     */
+    protected void removeSetterlessGetters(SerializationConfig config, BeanDescription beanDesc,
+            List<BeanPropertyDefinition> properties)
+    {
+        Iterator<BeanPropertyDefinition> it = properties.iterator();
+        while (it.hasNext()) {
+            BeanPropertyDefinition property = it.next();
+            // one caveat: as per [JACKSON-806], only remove implicit properties;
+            // explicitly annotated ones should remain
+            if (!property.couldDeserialize() && !property.isExplicitlyIncluded()) {
+                it.remove();
+            }
+        }
+    }
+    
+    /*
+    /**********************************************************
+    /* Internal helper methods
+    /**********************************************************
+     */
+
+    /**
+     * Secondary helper method for constructing {@link BeanPropertyWriter} for
+     * given member (field or method).
+     */
+    protected BeanPropertyWriter _constructWriter(SerializerProvider prov,
+            BeanPropertyDefinition propDef, TypeBindings typeContext,
+            PropertyBuilder pb, boolean staticTyping, AnnotatedMember accessor)
+        throws JsonMappingException
+    {
+        final PropertyName name = propDef.getFullName();
+        if (prov.canOverrideAccessModifiers()) {
+            accessor.fixAccess();
+        }
+        JavaType type = accessor.getType(typeContext);
+        BeanProperty.Std property = new BeanProperty.Std(name, type, propDef.getWrapperName(),
+                pb.getClassAnnotations(), accessor, propDef.getMetadata());
+
+        // Does member specify a serializer? If so, let's use it.
+        JsonSerializer<?> annotatedSerializer = findSerializerFromAnnotation(prov,
+                accessor);
+        /* 02-Feb-2012, tatu: Unlike most other code paths, serializer produced
+         *  here will NOT be resolved or contextualized, unless done here, so:
+         */
+        if (annotatedSerializer instanceof ResolvableSerializer) {
+            ((ResolvableSerializer) annotatedSerializer).resolve(prov);
+        }
+        // 05-Sep-2013, tatu: should be primary property serializer so:
+        annotatedSerializer = prov.handlePrimaryContextualization(annotatedSerializer, property);
+        // And how about polymorphic typing? First special to cover JAXB per-field settings:
+        TypeSerializer contentTypeSer = null;
+        // 16-Feb-2014, cgc: contentType serializers for collection-like and map-like types
+        if (ClassUtil.isCollectionMapOrArray(type.getRawClass()) || type.isCollectionLikeType() || type.isMapLikeType()) {
+            contentTypeSer = findPropertyContentTypeSerializer(type, prov.getConfig(), accessor);
+        }
+        // and if not JAXB collection/array with annotations, maybe regular type info?
+        TypeSerializer typeSer = findPropertyTypeSerializer(type, prov.getConfig(), accessor);
+        BeanPropertyWriter pbw = pb.buildWriter(prov, propDef, type, annotatedSerializer,
+                        typeSer, contentTypeSer, accessor, staticTyping);
+        return pbw;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.rej b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.rej
new file mode 100644
index 0000000..c243c36
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java.rej
@@ -0,0 +1,36 @@
+***************
+*** 391,404 ****
+              JavaType valueType = type.getContentType();
+              TypeSerializer typeSer = createTypeSerializer(config, valueType);
+              // last 2 nulls; don't know key, value serializers (yet)
+-             // TODO: support '@JsonIgnoreProperties' with any setter?
+-             MapSerializer mapSer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
+-                     typeSer, null, null, /*filterId*/ null);
+              // TODO: can we find full PropertyName?
+              PropertyName name = PropertyName.construct(anyGetter.getName());
+              BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null,
+                      beanDesc.getClassAnnotations(), anyGetter, PropertyMetadata.STD_OPTIONAL);
+-             builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, mapSer));
+          }
+          // Next: need to gather view information, if any:
+          processViews(config, builder);
+--- 391,409 ----
+              JavaType valueType = type.getContentType();
+              TypeSerializer typeSer = createTypeSerializer(config, valueType);
+              // last 2 nulls; don't know key, value serializers (yet)
++ 
++             // 23-Feb-2015, tatu: As per [#705], need to support custom serializers
++             JsonSerializer<?> anySer = findSerializerFromAnnotation(prov, anyGetter);
++             if (anySer == null) {
++                 // TODO: support '@JsonIgnoreProperties' with any setter?
++                 anySer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping,
++                         typeSer, null, null, /*filterId*/ null);
++             }
+              // TODO: can we find full PropertyName?
+              PropertyName name = PropertyName.construct(anyGetter.getName());
+              BeanProperty.Std anyProp = new BeanProperty.Std(name, valueType, null,
+                      beanDesc.getClassAnnotations(), anyGetter, PropertyMetadata.STD_OPTIONAL);
++             builder.setAnyGetter(new AnyGetterWriter(anyProp, anyGetter, anySer));
+          }
+          // Next: need to gather view information, if any:
+          processViews(config, builder);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
index fec2318..ee8735c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
@@ -342,6 +342,7 @@
 
         // also, any-getter may need to be resolved
         if (_anyGetterWriter != null) {
+            // 23-Feb-2015, tatu: Misleading, as this actually triggers call to contextualization...
             _anyGetterWriter.resolve(provider);
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
index 1b855da..cc9998f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnyGetter.java
@@ -1,12 +1,17 @@
 package com.fasterxml.jackson.databind.ser;
 
+import java.io.IOException;
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.*;
-
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
 
 public class TestAnyGetter extends BaseMapTest
 {
@@ -46,7 +51,43 @@
             stuff.put(key, value);
         }
     }
-    
+
+    static class Issue705Bean
+    {
+        protected Map<String,String> stuff;
+
+        public Issue705Bean(String key, String value) {
+            stuff = new LinkedHashMap<String,String>();
+            stuff.put(key, value);
+        }
+        
+        @JsonSerialize(using = Issue705Serializer.class)
+//    @JsonSerialize(converter = MyConverter.class)
+        @JsonAnyGetter
+        public Map<String, String> getParameters(){
+            return stuff;
+        }
+    }
+
+    @SuppressWarnings("serial")
+    static class Issue705Serializer extends StdSerializer<Object>
+    {
+        public Issue705Serializer() {
+            super(Map.class, false);
+        }
+
+        @Override
+        public void serialize(Object value, JsonGenerator jgen,
+                SerializerProvider provider) throws IOException
+        {
+            StringBuilder sb = new StringBuilder();
+            for (Map.Entry<?,?> entry : ((Map<?,?>) value).entrySet()) {
+                sb.append('[').append(entry.getKey()).append('/').append(entry.getValue()).append(']');
+            }
+            jgen.writeStringField("stuff", sb.toString());
+        }
+    }
+
     /*
     /**********************************************************
     /* Test cases
@@ -90,4 +131,11 @@
         assertEquals(aposToQuotes("{'bar':null}"),
                 MAPPER.writeValueAsString(input));
     }
+
+    public void testIssue705() throws Exception
+    {
+        Issue705Bean input = new Issue705Bean("key", "value");        
+        String json = MAPPER.writeValueAsString(input);
+        assertEquals("{\"stuff\":\"[key/value]\"}", json);
+    }
 }