openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kevin Sutter" <kwsut...@gmail.com>
Subject Re: svn commit: r698284 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ openjpa-slice/src/main/java/org/apache/openjpa/slice/ openjpa-slice/src/main/java/org
Date Tue, 23 Sep 2008 19:38:42 GMT
Pinaki,
I know I'm being a pain in the butt...  But, wouldn't these changes also
require doc updates?  ;-)

Thanks,
Kevin

On Tue, Sep 23, 2008 at 1:58 PM, <ppoddar@apache.org> wrote:

> Author: ppoddar
> Date: Tue Sep 23 11:58:00 2008
> New Revision: 698284
>
> URL: http://svn.apache.org/viewvc?rev=698284&view=rev
> Log:
> Introduces notion of @Replicated entity. This feature allows to relax
> collocation constraint for quasi-stationary master data. A replicated entity
> is stored as identical copies across multiple slices. The
> ReplicationStrategy works similar to DistributionStrategy for replicated
> entity. The slice association cardinality has uniformly changed to array of
> slices from a single slice name both for replicated and non-replicated
> entity. The non-replicated entities can refer to replicated entities but not
> vice versa. The query operation (especially the ones with aggregate
> function) is aware of replicated data and queries only one of the slices to
> avoid duplication.
>
> Added:
>
>  openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java
>
>  openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java
> Modified:
>
>  openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
>
>  openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
>
>  openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java
>
>  openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java
>
>  openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java
>
>  openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java
>    openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml
>
> Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
> (original)
> +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
> Tue Sep 23 11:58:00 2008
> @@ -164,7 +164,8 @@
>     private int _identity = ID_UNKNOWN;
>     private int _idStrategy = ValueStrategies.NONE;
>     private int _accessType = ACCESS_UNKNOWN;
> -
> +    private boolean _replicated = false;
> +
>     private String _seqName = DEFAULT_STRING;
>     private SequenceMetaData _seqMeta = null;
>     private String _cacheName = DEFAULT_STRING;
> @@ -2401,4 +2402,20 @@
>        Collections.sort(result);
>        return result.toArray(new String[result.size()]);
>     }
> +
> +    /**
> +     * Affirms the persistence instances of this receiver is replicated
> across
> +     * multiple databases.
> +     */
> +    public boolean isReplicated() {
> +       return _replicated;
> +    }
> +
> +    /**
> +     * Sets the persistence instances of this receiver to be replicated
> across
> +     * multiple databases.
> +     */
> +    public void setReplicated(boolean flag) {
> +       _replicated = flag;
> +    }
>  }
>
> Modified:
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
> (original)
> +++
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
> Tue Sep 23 11:58:00 2008
> @@ -175,6 +175,7 @@
>         _tags.put(ManagedInterface.class, MANAGED_INTERFACE);
>         _tags.put(ReadOnly.class, READ_ONLY);
>         _tags.put(Type.class, TYPE);
> +        _tags.put(Replicated.class, REPLICATED);
>     }
>
>     private final OpenJPAConfiguration _conf;
> @@ -577,6 +578,9 @@
>                     if (isMetaDataMode())
>                         parseManagedInterface(meta, (ManagedInterface)
> anno);
>                     break;
> +                case REPLICATED:
> +                       meta.setReplicated(true);
> +                       break;
>                 default:
>                     throw new UnsupportedException(_loc.get("unsupported",
> _cls,
>                         anno.toString()));
>
> Modified:
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
> (original)
> +++
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
> Tue Sep 23 11:58:00 2008
> @@ -80,4 +80,5 @@
>     MANAGED_INTERFACE,
>     READ_ONLY,
>     TYPE,
> +    REPLICATED
>  }
>
> Added:
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java?rev=698284&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java
> (added)
> +++
> openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/Replicated.java
> Tue Sep 23 11:58:00 2008
> @@ -0,0 +1,44 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.persistence;
> +
> +import static java.lang.annotation.ElementType.TYPE;
> +import static java.lang.annotation.RetentionPolicy.RUNTIME;
> +
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.Target;
> +
> +/**
> + * Annotation to specify the instance of the annotated entity be
> + * replicated across more than one <em>slices</em>. The actual slices
> where an
> + * instance of the annotated entity will be replicated is determined by
> + * the return value of user-specified
> + * {@link ReplicationPolicy#replicate(Object, java.util.List, Object)}
> + * method.
> + *
> + * @see ReplicationPolicy
> + *
> + * @author Pinaki Poddar
> + *
> + */
> +@Target({ TYPE })
> +@Retention(RUNTIME)
> +public @interface Replicated {
> +
> +}
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedBrokerImpl.java
> Tue Sep 23 11:58:00 2008
> @@ -22,7 +22,6 @@
>  import org.apache.openjpa.kernel.OpCallbacks;
>  import org.apache.openjpa.kernel.OpenJPAStateManager;
>  import org.apache.openjpa.lib.util.Localizer;
> -import org.apache.openjpa.util.UserException;
>
>  /**
>  * A specialized Broker to associate slice identifiers with the
> StateManagers as
> @@ -36,11 +35,17 @@
>  */
>  @SuppressWarnings("serial")
>  public class DistributedBrokerImpl extends FinalizingBrokerImpl {
> -       private transient String slice;
> -
> +       private transient String _rootSlice;
> +       private transient DistributedConfiguration _conf;
>        private static final Localizer _loc =
>                        Localizer.forPackage(DistributedBrokerImpl.class);
>
> +    public DistributedConfiguration getConfiguration() {
> +       if (_conf == null) {
> +               _conf = (DistributedConfiguration)super.getConfiguration();
> +       }
> +        return _conf;
> +    }
>        /**
>         * Assigns slice identifier to the resultant StateManager as
> initialized by
>         * the super class implementation. The slice identifier is decided
> by
> @@ -54,32 +59,28 @@
>        public OpenJPAStateManager persist(Object pc, Object id, boolean
> explicit,
>                        OpCallbacks call) {
>                OpenJPAStateManager sm = getStateManager(pc);
> +               String[] targets = null;
> +               boolean replicated = SliceImplHelper.isReplicated(sm);
>                if (getOperatingSet().isEmpty()
> -                               && (sm == null || sm.getImplData() ==
> null)) {
> -                       slice = getSlice(pc);
> +                       && (sm == null || sm.getImplData() == null)) {
> +                       targets = SliceImplHelper.getSlicesByPolicy(pc,
> getConfiguration(),
> +                               this);
> +                       if (!replicated) {
> +                               _rootSlice = targets[0];
> +                       }
>                }
>                sm = super.persist(pc, id, explicit, call);
> -               if (sm.getImplData() == null)
> -                       sm.setImplData(slice, true);
> -
> +               if (sm.getImplData() == null) {
> +                       if (targets == null) {
> +                          targets = replicated
> +                          ? SliceImplHelper.getSlicesByPolicy(pc,
> getConfiguration(), this)
> +                          : new String[]{_rootSlice};
> +                       }
> +                       sm.setImplData(targets, true);
> +               }
>                return sm;
>        }
>
> -       /**
> -        * Gets the slice by the user-defined distribution policy.
> -        */
> -       String getSlice(Object pc) {
> -               DistributedConfiguration conf =
> -                               (DistributedConfiguration)
> getConfiguration();
> -               String slice =
> -
> (conf.getDistributionPolicyInstance().distribute(pc, conf
> -                                               .getActiveSliceNames(),
> this));
> -               if (!conf.getActiveSliceNames().contains(slice))
> -                       throw new
> UserException(_loc.get("bad-policy-slice", new Object[] {
> -
> conf.getDistributionPolicyInstance().getClass().getName(),
> -                                       slice, pc,
> conf.getActiveSliceNames() }));
> -               return slice;
> -       }
>
>        @Override
>        public boolean endOperation() {
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributedConfiguration.java
> Tue Sep 23 11:58:00 2008
> @@ -75,4 +75,10 @@
>         * the available slices.
>         */
>        DistributionPolicy getDistributionPolicyInstance();
> +
> +       /**
> +        * Gets the policy that governs how new replicated instances will
> be
> +        * replicated across the available slices.
> +        */
> +       ReplicationPolicy getReplicationPolicyInstance();
>  }
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/DistributionPolicy.java
> Tue Sep 23 11:58:00 2008
> @@ -19,6 +19,7 @@
>  package org.apache.openjpa.slice;
>
>  import java.util.List;
> +import java.util.Random;
>
>
>  /**
> @@ -44,4 +45,16 @@
>         * @see DistributedConfiguration#getActiveSliceNames()
>         */
>        String distribute(Object pc, List<String> slices, Object context);
> +
> +       /**
> +        * Implements a default distribution policy to store the given
> +        * instance to a randomly selected available slice.
> +        *
> +        */
> +       public static class Default implements DistributionPolicy {
> +               private static Random RNG = new Random();
> +               public String distribute(Object pc, List<String> slices,
> Object ctx) {
> +                       return slices.get(RNG.nextInt(slices.size()));
> +               }
> +       }
>  }
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ProductDerivation.java
> Tue Sep 23 11:58:00 2008
> @@ -22,7 +22,9 @@
>
>  import org.apache.openjpa.conf.OpenJPAProductDerivation;
>  import org.apache.openjpa.lib.conf.AbstractProductDerivation;
> +import org.apache.openjpa.lib.conf.Configuration;
>  import org.apache.openjpa.slice.jdbc.DistributedJDBCBrokerFactory;
> +import org.apache.openjpa.slice.jdbc.DistributedJDBCConfigurationImpl;
>
>  /**
>  * Derives configuration for Slice.
> @@ -58,6 +60,28 @@
>        }
>
>        public int getType() {
> -               return TYPE_FEATURE;
> +               return TYPE_STORE;
>        }
> +
> +       /**
> +        * Sets the {@link DistributionPolicy} and {@link
> ReplicationPolicy} to
> +        * their respective defaults if not set by the user.
> +        */
> +    @Override
> +    public boolean afterSpecificationSet(Configuration c) {
> +        if (!(c instanceof DistributedJDBCConfigurationImpl))
> +            return false;
> +        DistributedJDBCConfigurationImpl conf =
> +               (DistributedJDBCConfigurationImpl)c;
> +        boolean modified = false;
> +        if (conf.getDistributionPolicyInstance() == null) {
> +               conf.distributionPolicyPlugin.setString("random");
> +               modified = true;
> +        }
> +        if (conf.getReplicationPolicyInstance() == null) {
> +               conf.replicationPolicyPlugin.setString("all");
> +               modified = true;
> +        }
> +        return modified;
> +    }
>  }
>
> Added:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java?rev=698284&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java
> (added)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/ReplicationPolicy.java
> Tue Sep 23 11:58:00 2008
> @@ -0,0 +1,60 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.slice;
> +
> +import java.util.List;
> +
> +
> +/**
> + * Policy to select one of the physical databases referred as
> <em>slice</em>
> + * in which a given persistent instance will be replicated.
> + *
> + * @author Pinaki Poddar
> + *
> + */
> +public interface ReplicationPolicy {
> +       /**
> +        * Gets the name of the slices where a given instance will be
> replicated.
> +        *
> +        * @param pc The newly persistent or to-be-merged object.
> +        * @param slices list of names of the active slices. The ordering
> of
> +        * the list is either explicit <code>openjpa.slice.Names</code>
> property
> +        * or implicit i.e. alphabetic order of available identifiers if
> +        * <code>openjpa.slice.Names</code> is unspecified.
> +        * @param context generic persistence context managing the given
> instance.
> +        *
> +        * @return identifier of the slices. This names must match one of
> the
> +        * given slice names. Return null or empty list to imply all active
> slices.
> +        *
> +        * @see DistributedConfiguration#getActiveSliceNames()
> +        */
> +       String[] replicate(Object pc, List<String> slices, Object context);
> +
> +       /**
> +        * Implements a default replication policy to replicate the given
> +        * instance across all available slices.
> +        *
> +        */
> +       public static class Default implements ReplicationPolicy {
> +               public String[] replicate(Object pc, List<String> slices,
> +                       Object context) {
> +                       return null;
> +               }
> +       }
> +}
>
> Added:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java?rev=698284&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java
> (added)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceImplHelper.java
> Tue Sep 23 11:58:00 2008
> @@ -0,0 +1,88 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.slice;
> +
> +import java.util.List;
> +
> +import org.apache.openjpa.conf.OpenJPAConfiguration;
> +import org.apache.openjpa.kernel.OpenJPAStateManager;
> +import org.apache.openjpa.lib.util.Localizer;
> +import org.apache.openjpa.meta.ClassMetaData;
> +import org.apache.openjpa.util.UserException;
> +
> +/**
> + * Utility methods to determine the target slices for a persistence
> capable
> + * instance by calling back to user-specified distribution policy.
> + *
> + * @author Pinaki Poddar
> + *
> + */
> +public class SliceImplHelper {
> +       private static final Localizer _loc =
> +               Localizer.forPackage(SliceImplHelper.class);
> +
> +       /**
> +        * Gets the target slices by calling user-specified
> +        * {@link DistributionPolicy} or {@link ReplicationPolicy}
> +        * depending on whether the given instance is {@link Replicated
> replicated}.
> +        */
> +       public static String[] getSlicesByPolicy(Object pc,
> +                       DistributedConfiguration conf, Object ctx) {
> +               List<String> availables = conf.getActiveSliceNames();
> +               Object policy = null;
> +               String[] targets = null;
> +               if (isReplicated(pc, conf)) {
> +                       policy = conf.getReplicationPolicyInstance();
> +                       targets = ((ReplicationPolicy)policy).replicate
> +                               (pc, availables, ctx);
> +                       if (targets == null || targets.length == 0)
> +                               targets = availables.toArray(new
> String[availables.size()]);
> +               } else {
> +                       policy = conf.getDistributionPolicyInstance();
> +                       String slice =
> ((DistributionPolicy)policy).distribute
> +                               (pc, availables, ctx);
> +                       targets = new String[]{slice};
> +               }
> +               for (String target : targets)
> +                       if (!availables.contains(target))
> +                       throw new
> UserException(_loc.get("bad-policy-slice", new Object[] {
> +                                       policy.getClass().getName(),
> target, pc, availables}));
> +               return targets;
> +       }
> +
> +       /**
> +        * Affirms if the given instance be replicated to multiple slices.
> +        */
> +       public static boolean isReplicated(Object pc, OpenJPAConfiguration
> conf) {
> +               if (pc == null)
> +                       return false;
> +               ClassMetaData meta = conf.getMetaDataRepositoryInstance()
> +                       .getMetaData(pc.getClass(), null, false);
> +               return (meta == null) ? false : meta.isReplicated();
> +       }
> +
> +       /**
> +        * Affirms if the given instance be replicated to multiple slices.
> +        */
> +       public static boolean isReplicated(OpenJPAStateManager sm) {
> +               if (sm == null)
> +                       return false;
> +               return sm.getMetaData().isReplicated();
> +       }
> +}
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SlicePersistence.java
> Tue Sep 23 11:58:00 2008
> @@ -18,6 +18,8 @@
>  */
>  package org.apache.openjpa.slice;
>
> +import java.util.Arrays;
> +
>  import org.apache.openjpa.enhance.PersistenceCapable;
>  import org.apache.openjpa.kernel.StateManagerImpl;
>  import org.apache.openjpa.util.ImplHelper;
> @@ -32,6 +34,8 @@
>        /**
>         * Get the slice identifier for the given instance if it is a
> managed
>         * instance and has been assigned to a slice.
> +        * If the given instance is replicated across multiple slices then
> returns
> +        * comma-separated list of slice names.
>         *
>         * @return name of the slice, if any. null otherwise.
>         */
> @@ -45,6 +49,13 @@
>                if (sm == null)
>                        return null;
>                Object slice = sm.getImplData();
> -               return (slice instanceof String) ? (String)slice : null;
> +               if (slice instanceof String[]) {
> +                       if (((String[])slice).length == 1) {
> +                               return ((String[])slice)[0];
> +                       } else {
> +                               return Arrays.toString(((String[])slice));
> +                       }
> +               }
> +               return null;
>        }
>  }
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedJDBCConfigurationImpl.java
> Tue Sep 23 11:58:00 2008
> @@ -49,6 +49,7 @@
>  import org.apache.openjpa.slice.DistributionPolicy;
>  import org.apache.openjpa.slice.ExecutorServiceValue;
>  import org.apache.openjpa.slice.ProductDerivation;
> +import org.apache.openjpa.slice.ReplicationPolicy;
>  import org.apache.openjpa.slice.Slice;
>  import org.apache.openjpa.util.UserException;
>
> @@ -73,11 +74,13 @@
>     protected StringValue masterPlugin;
>     protected StringListValue namesPlugin;
>     protected ExecutorServiceValue executorServicePlugin;
> -    protected PluginValue distributionPolicyPlugin;
> +    public PluginValue distributionPolicyPlugin;
> +    public PluginValue replicationPolicyPlugin;
>
>     public static final String DOT = ".";
>     public static final String REGEX_DOT = "\\.";
> -    public static final String PREFIX_SLICE =
> ProductDerivation.PREFIX_SLICE + DOT;
> +    public static final String PREFIX_SLICE =
> ProductDerivation.PREFIX_SLICE +
> +       DOT;
>     public static final String PREFIX_OPENJPA = "openjpa.";
>     private static Localizer _loc =
>             Localizer.forPackage(DistributedJDBCConfigurationImpl.class);
> @@ -95,8 +98,18 @@
>         brokerPlugin.setString(DistributedBrokerImpl.class.getName());
>
>         distributionPolicyPlugin = addPlugin("DistributionPolicy", true);
> +        distributionPolicyPlugin.setAlias("random",
> +               DistributionPolicy.Default.class.getName());
> +        distributionPolicyPlugin.setDefault("random");
>         distributionPolicyPlugin.setDynamic(true);
>
> +        replicationPolicyPlugin = addPlugin
> +               ("ReplicatedDistributionPolicy", true);
> +        replicationPolicyPlugin.setAlias("all",
> +               ReplicationPolicy.Default.class.getName());
> +        replicationPolicyPlugin.setDefault("all");
> +        replicationPolicyPlugin.setDynamic(true);
> +
>         lenientPlugin = addBoolean("Lenient");
>
>         masterPlugin = addString("Master");
> @@ -185,6 +198,18 @@
>     }
>
>     public void setDistributionPolicyInstance(String val) {
> +       replicationPolicyPlugin.set(val);
> +    }
> +
> +    public ReplicationPolicy getReplicationPolicyInstance() {
> +        if (replicationPolicyPlugin.get() == null) {
> +
> replicationPolicyPlugin.instantiate(ReplicationPolicy.class,
> +                    this, true);
> +        }
> +        return (ReplicationPolicy) replicationPolicyPlugin.get();
> +    }
> +
> +    public void setReplicatedDistributionPolicyInstance(String val) {
>         distributionPolicyPlugin.set(val);
>     }
>
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreManager.java
> Tue Sep 23 11:58:00 2008
> @@ -18,6 +18,7 @@
>  */
>  package org.apache.openjpa.slice.jdbc;
>
> +import java.io.IOException;
>  import java.sql.Connection;
>  import java.sql.SQLException;
>  import java.util.ArrayList;
> @@ -42,6 +43,7 @@
>  import org.apache.openjpa.kernel.FetchConfiguration;
>  import org.apache.openjpa.kernel.OpenJPAStateManager;
>  import org.apache.openjpa.kernel.PCState;
> +import org.apache.openjpa.kernel.QueryContext;
>  import org.apache.openjpa.kernel.QueryLanguages;
>  import org.apache.openjpa.kernel.Seq;
>  import org.apache.openjpa.kernel.StoreContext;
> @@ -54,10 +56,15 @@
>  import org.apache.openjpa.meta.ClassMetaData;
>  import org.apache.openjpa.meta.FieldMetaData;
>  import org.apache.openjpa.slice.DistributionPolicy;
> +import org.apache.openjpa.slice.SliceImplHelper;
>  import org.apache.openjpa.slice.ProductDerivation;
> +import org.apache.openjpa.slice.ReplicationPolicy;
>  import org.apache.openjpa.util.InternalException;
>  import org.apache.openjpa.util.StoreException;
>  import org.apache.openjpa.util.UserException;
> +import org.apache.tools.ant.taskdefs.condition.IsReference;
> +
> +import sun.reflect.ReflectionFactory.GetReflectionFactoryAction;
>
>  /**
>  * A Store manager for multiple physical databases referred as
> <em>slice</em>.
> @@ -109,71 +116,70 @@
>
>     /**
>      * Decides the index of the StoreManager by first looking at the
> -     * implementation data. If not found then {@link DistributionPolicy
> -     * DistributionPolicy} determines the target store for new instances
> and
> -     * additional connection info is used to estimate for the existing
> -     * instances.
> +     * implementation data. If no implementation data is found, then
> estimates
> +     * targets slices by using additional connection info. If no
> additional
> +     * connection info then calls back to user-defined policy.
>      */
> -    protected String findSliceName(OpenJPAStateManager sm, Object info) {
> -        boolean hasIndex = hasSlice(sm);
> -        if (hasIndex)
> -            return sm.getImplData().toString();
> -        String slice = estimateSlice(sm, info);
> -        if (slice == null)
> +    protected String[] findSliceNames(OpenJPAStateManager sm, Object info)
> {
> +        boolean hasImplData = sm.getImplData() != null;
> +        if (hasImplData)
> +            return (String[])sm.getImplData();
> +        String[] targets = estimateSlice(sm, info);
> +        if (targets == null)
>             return assignSlice(sm);
> -        return slice;
> -    }
> -
> -    private boolean hasSlice(OpenJPAStateManager sm) {
> -        return sm.getImplData() != null;
> +        return targets;
>     }
> -
> -    private String assignSlice(OpenJPAStateManager sm) {
> -        Object pc = sm.getPersistenceCapable();
> -        DistributionPolicy policy = _conf.getDistributionPolicyInstance();
> -        List<String> sliceNames = _conf.getActiveSliceNames();
> -        String slice =policy.distribute(pc, sliceNames, getContext());
> -        if (!sliceNames.contains(slice)) {
> -            throw new UserException(_loc.get("bad-policy-slice", new
> Object[] {
> -                    policy.getClass().getName(), slice, pc, sliceNames
> }));
> -        }
> -        sm.setImplData(slice, true);
> -        return slice;
> +
> +    private String[] assignSlice(OpenJPAStateManager sm) {
> +       Object pc = sm.getPersistenceCapable();
> +       String[] targets = SliceImplHelper.getSlicesByPolicy(pc, _conf,
> +                       getContext());
> +        sm.setImplData(targets, true);
> +        return targets;
>     }
> -
> +
>     /**
>      * The additional edata is used, if possible, to find the StoreManager
>      * managing the given StateManager. If the additional data is
> unavailable
>      * then return null.
>      *
>      */
> -    private String estimateSlice(OpenJPAStateManager sm, Object edata) {
> +    private String[] estimateSlice(OpenJPAStateManager sm, Object edata) {
>         if (edata == null || !(edata instanceof ConnectionInfo))
>             return null;
>
> +        List<String> temps = null;
>         Result result = ((ConnectionInfo) edata).result;
>         if (result instanceof ResultSetResult) {
>             JDBCStore store = ((ResultSetResult) result).getStore();
>             for (SliceStoreManager slice : _slices) {
>                 if (slice == store) {
> -                    String sliceId = slice.getName();
> -                    sm.setImplData(sliceId, true);
> -                    return sliceId;
> +                       if (temps == null)
> +                               temps = new ArrayList<String>();
> +                    temps.add(slice.getName());
>                 }
>             }
>         }
> -        return null;
> +        if (temps != null) {
> +               String[] targets = temps.toArray(new String[temps.size()]);
> +               sm.setImplData(targets, true);
> +               return targets;
> +        }
> +        return null;
>     }
>
>     /**
> -     * Selects a child StoreManager where the given instance resides.
> +     * Selects child StoreManager(s) where the given instance resides.
>      */
>     private StoreManager selectStore(OpenJPAStateManager sm, Object edata)
> {
> -        String name = findSliceName(sm, edata);
> -        SliceStoreManager slice = lookup(name);
> -        if (slice == null)
> -            throw new InternalException(_loc.get("wrong-slice", name,
> sm));
> -        return slice;
> +        String[] targets = findSliceNames(sm, edata);
> +        for (String target : targets) {
> +               SliceStoreManager slice = lookup(target);
> +               if (slice == null)
> +                       throw new InternalException(_loc.get("wrong-slice",
> target, sm));
> +               return slice;
> +        }
> +        return null;
>     }
>
>     public boolean assignField(OpenJPAStateManager sm, int field,
> @@ -222,13 +228,16 @@
>     }
>
>     public boolean exists(OpenJPAStateManager sm, Object edata) {
> +       List<String> targets = null;
>         for (SliceStoreManager slice : _slices) {
>             if (slice.exists(sm, edata)) {
> -                sm.setImplData(slice.getName(), true);
> -                return true;
> +               if (targets == null)
> +                       targets.add(slice.getName());
>             }
>         }
> -        return false;
> +        if (targets != null)
> +               sm.setImplData(targets.toArray(new String[targets.size()]),
> true);
> +        return targets != null;
>     }
>
>
> @@ -244,7 +253,11 @@
>             List<OpenJPAStateManager> subset =
> subsets.get(slice.getName());
>             if (subset.isEmpty())
>                 continue;
> -            futures.add(threadPool.submit(new Flusher(slice, subset)));
> +            if (containsReplicated(subset)) {
> +               slice.flush(subset);
> +            } else {
> +               futures.add(threadPool.submit(new Flusher(slice, subset)));
> +            }
>         }
>         for (Future<Collection> future : futures) {
>             Collection error;
> @@ -262,12 +275,16 @@
>         return exceptions;
>     }
>
> +    boolean containsReplicated(List<OpenJPAStateManager> sms) {
> +       for (OpenJPAStateManager sm : sms)
> +               if (sm.getMetaData().isReplicated())
> +                       return true;
> +       return false;
> +    }
> +
>     /**
>      * Separate the given list of StateManagers in separate lists for each
> slice
>      * by the associated slice identifier of each StateManager.
> -     * @param sms
> -     * @param edata
> -     * @return
>      */
>     private Map<String, List<OpenJPAStateManager>> bin(
>             Collection/*<StateManage>*/ sms, Object edata) {
> @@ -277,8 +294,10 @@
>             subsets.put(slice.getName(), new
> ArrayList<OpenJPAStateManager>());
>         for (Object x : sms) {
>             OpenJPAStateManager sm = (OpenJPAStateManager) x;
> -            String slice = findSliceName(sm, edata);
> -            subsets.get(slice).add(sm);
> +            String[] targets = findSliceNames(sm, edata);
> +               for (String slice : targets) {
> +               subsets.get(slice).add(sm);
> +            }
>         }
>         return subsets;
>     }
> @@ -306,15 +325,15 @@
>     public boolean initialize(OpenJPAStateManager sm, PCState state,
>             FetchConfiguration fetch, Object edata) {
>         if (edata instanceof ConnectionInfo) {
> -            String slice = findSliceName(sm, (ConnectionInfo) edata);
> -            if (slice != null)
> -                return lookup(slice).initialize(sm, state, fetch, edata);
> +            String[] targets = findSliceNames(sm, (ConnectionInfo) edata);
> +            if (targets != null || targets.length > 0)
> +                return lookup(targets[0]).initialize(sm, state, fetch,
> edata);
>         }
>         // not a part of Query result load. Look into the slices till found
>         List<SliceStoreManager> targets = getTargets(fetch);
>         for (SliceStoreManager slice : targets) {
>             if (slice.initialize(sm, state, fetch, edata)) {
> -                sm.setImplData(slice.getName(), true);
> +                sm.setImplData(new String[]{slice.getName()}, true);
>                 return true;
>             }
>         }
> @@ -381,7 +400,13 @@
>     }
>
>     public boolean syncVersion(OpenJPAStateManager sm, Object edata) {
> -        return selectStore(sm, edata).syncVersion(sm, edata);
> +       String[] targets = findSliceNames(sm, edata);
> +       boolean sync = true;
> +       for (String replica : targets) {
> +               SliceStoreManager slice = lookup(replica);
> +               sync &= slice.syncVersion(sm, edata);
> +       }
> +       return sync;
>     }
>
>     @Override
>
> Modified:
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/jdbc/DistributedStoreQuery.java
> Tue Sep 23 11:58:00 2008
> @@ -77,7 +77,7 @@
>
>     public void setContext(QueryContext ctx) {
>        super.setContext(ctx);
> -       for (StoreQuery q:_queries)
> +       for (StoreQuery q : _queries)
>                q.setContext(ctx);
>     }
>
> @@ -124,6 +124,9 @@
>                        StoreManager sm  =
> owner.getDistributedStore().getSlice(i);
>                        if (!targets.contains(sm))
>                                continue;
> +                       // if replicated, then execute only on single slice
> +                       if (i > 0 &&
> containsReplicated(query.getContext()))
> +                               continue;
>                        QueryExecutor call = new QueryExecutor();
>                        call.executor = executors.get(i);
>                        call.query    = query;
> @@ -164,6 +167,27 @@
>                return result;
>         }
>
> +        /**
> +                * Scans metadata to find out if a replicated class is the
> candidate.
> +        **/
> +        boolean containsReplicated(QueryContext query) {
> +               Class candidate = query.getCandidateType();
> +               if (candidate != null) {
> +                       ClassMetaData meta =
> query.getStoreContext().getConfiguration()
> +                               .getMetaDataRepositoryInstance()
> +                               .getMetaData(candidate, null, true);
> +                       if (meta != null && meta.isReplicated())
> +                               return true;
> +               }
> +               ClassMetaData[] metas = query.getAccessPathMetaDatas();
> +               if (metas == null || metas.length < 1)
> +                       return false;
> +               for (ClassMetaData type : metas)
> +                       if (type.isReplicated())
> +                               return true;
> +               return false;
> +        }
> +
>         public Number executeDelete(StoreQuery q, Object[] params) {
>                Iterator<StoreQuery> qs = owner._queries.iterator();
>                final List<Future<Number>> futures = new
> ArrayList<Future<Number>>();
>
> Modified:
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Address.java
> Tue Sep 23 11:58:00 2008
> @@ -28,6 +28,9 @@
>
>     private String city;
>     private int zip;
> +
> +    @OneToOne
> +    private Country country;
>
>     @OneToOne(mappedBy = "address")
>     Person owner;
> @@ -79,4 +82,12 @@
>     public String toString() {
>         return city;
>     }
> +
> +       public Country getCountry() {
> +               return country;
> +       }
> +
> +       public void setCountry(Country country) {
> +               this.country = country;
> +       }
>  }
>
> Added:
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java?rev=698284&view=auto
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java
> (added)
> +++
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/Country.java
> Tue Sep 23 11:58:00 2008
> @@ -0,0 +1,56 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.openjpa.slice;
> +
> +import javax.persistence.Entity;
> +import javax.persistence.Id;
> +
> +import org.apache.openjpa.persistence.Replicated;
> +
> +/**
> + * A persistence entity to be replicated across multiple databases.
> + * A non-replicated entity can refer to a replicated entity.
> + *
> + * @author Pinaki Poddar
> + *
> + */
> +@Entity
> +@Replicated
> +public class Country {
> +       @Id
> +       private String name;
> +
> +       private long population;
> +
> +       public String getName() {
> +               return name;
> +       }
> +
> +       public void setName(String name) {
> +               this.name = name;
> +       }
> +
> +       public long getPopulation() {
> +               return population;
> +       }
> +
> +       public void setPopulation(long population) {
> +               this.population = population;
> +       }
> +}
>
> Modified:
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> ---
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java
> (original)
> +++
> openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java
> Tue Sep 23 11:58:00 2008
> @@ -30,18 +30,22 @@
>  *
>  */
>  public class TestBasic extends SliceTestCase {
> -
> +    /**
> +     * Specify persistence unit name as System property
> <code>-Dunit</code> or
> +     * use the default value as <code>"slice"</code>.
> +     */
>     protected String getPersistenceUnitName() {
> -        return "slice";
> +        return System.getProperty("unit","slice");
>     }
>
>
>     public void setUp() throws Exception {
> -        super.setUp(PObject.class, Person.class, Address.class,
> CLEAR_TABLES);
> +        super.setUp(PObject.class, Person.class, Address.class,
> Country.class,
> +               CLEAR_TABLES);
>     }
>
>     /**
> -     * Persist N objects.
> +     * Persist N independent objects.
>      */
>     List<PObject> create(int N) {
>         List<PObject> pcs = new ArrayList<PObject>();
> @@ -128,18 +132,25 @@
>     }
>
>     public void testPersistConnectedObjectGraph() {
> +        EntityManager em = emf.createEntityManager();
> +        em.getTransaction().begin();
>         Person p1 = new Person("A");
>         Person p2 = new Person("B");
>         Person p3 = new Person("C");
>         Address a1 = new Address("Rome", 12345);
>         Address a2 = new Address("San Francisco", 23456);
>         Address a3 = new Address("New York", 34567);
> +        Country c1 = em.find(Country.class, "Italy");
> +        if (c1 == null) {
> +               c1 = new Country();
> +               c1.setName("Italy");
> +               em.persist(c1);
> +        }
> +       a1.setCountry(c1);
>         p1.setAddress(a1);
>         p2.setAddress(a2);
>         p3.setAddress(a3);
>
> -        EntityManager em = emf.createEntityManager();
> -        em.getTransaction().begin();
>         em.persist(p1);
>         em.persist(p2);
>         em.persist(p3);
> @@ -185,5 +196,46 @@
>         assertEquals(pc.getId(), pc2.getId());
>         assertEquals(value + 1, pc2.getValue());
>     }
> +
> +    public void testPersistReplicatedObjects() {
> +        EntityManager em = emf.createEntityManager();
> +        em.getTransaction().begin();
> +        String[] names = {"USA", "India", "China"};
> +        for (String name : names) {
> +               Country country = new Country();
> +               country.setName(name);
> +               em.persist(country);
> +        }
> +        em.getTransaction().commit();
> +        assertEquals(names.length, count(Country.class));
> +
> +        Country india = em.find(Country.class, "India");
> +        assertNotNull(india);
> +        assertEquals("India", india.getName());
> +    }
> +
> +    public void testUpdateReplicatedObjects() {
> +        EntityManager em = emf.createEntityManager();
> +        em.getTransaction().begin();
> +        String[] names = {"USA", "India", "China"};
> +        long[] population = {300,1200,1400};
> +        for (int i = 0; i < names.length; i++) {
> +               Country country = new Country();
> +               country.setName(names[i]);
> +               country.setPopulation(population[i]);
> +               em.persist(country);
> +        }
> +        em.getTransaction().commit();
> +
> +        assertEquals(names.length, count(Country.class));
> +        Country india = em.find(Country.class, "India");
> +
> +        assertNotNull(india);
> +        assertEquals("India", india.getName());
> +        india.setPopulation(1201);
> +        em.getTransaction().begin();
> +        em.merge(india);
> +        em.getTransaction().commit();
> +    }
>
>  }
>
> Modified:
> openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml
> URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml?rev=698284&r1=698283&r2=698284&view=diff
>
> ==============================================================================
> --- openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml
> (original)
> +++ openjpa/trunk/openjpa-slice/src/test/resources/META-INF/persistence.xml
> Tue Sep 23 11:58:00 2008
> @@ -22,6 +22,7 @@
>         <class>org.apache.openjpa.slice.PObject</class>
>         <class>org.apache.openjpa.slice.Person</class>
>         <class>org.apache.openjpa.slice.Address</class>
> +        <class>org.apache.openjpa.slice.Country</class>
>         <properties>
>          <property name="openjpa.Log" value="DefaultLevel=WARN,
> Enhance=TRACE"/>
>         </properties>
> @@ -83,6 +84,7 @@
>         <class>org.apache.openjpa.slice.PObject</class>
>         <class>org.apache.openjpa.slice.Person</class>
>         <class>org.apache.openjpa.slice.Address</class>
> +        <class>org.apache.openjpa.slice.Country</class>
>                <properties>
>             <property name="openjpa.BrokerFactory" value="slice"/>
>             <property name="openjpa.ConnectionDriverName"
> value="org.apache.derby.jdbc.EmbeddedDriver"/>
> @@ -122,4 +124,28 @@
>             <property name="openjpa.jdbc.MappingDefaults"
> value="DefaultMissingInfo=true"/>
>         </properties>
>    </persistence-unit>
> +
> +   <persistence-unit name="mysql">
> +      <properties>
> +         <property name="openjpa.BrokerFactory" value="slice"/>
> +         <property name="openjpa.ConnectionDriverName"
> value="com.mysql.jdbc.Driver"/>
> +
> +         <property name="openjpa.slice.Names" value="One,Two"/>
> +         <property name="openjpa.slice.DistributionPolicy"
> value="org.apache.openjpa.slice.policy.UserDistributionPolicy"/>
> +
> +         <property name="openjpa.ConnectionUserName"        value="root"/>
> +         <property name="openjpa.ConnectionPassword"        value=""/>
> +         <property name="openjpa.slice.One.ConnectionDriverName"
> value="com.mysql.jdbc.Driver"/>
> +         <property name="openjpa.slice.One.ConnectionURL"
> value="jdbc:mysql://localhost/slice1"/>
> +         <property name="openjpa.slice.Two.ConnectionDriverName"
> value="com.mysql.jdbc.Driver"/>
> +         <property name="openjpa.slice.Two.ConnectionURL"
> value="jdbc:mysql://localhost/slice2"/>
> +
> +         <property name="openjpa.Multithreaded" value="false"/>
> +         <property name="openjpa.Log" value="DefaultLevel=INFO,
> Enhance=TRACE, SQL=TRACE"/>
> +         <property name="openjpa.jdbc.SynchronizeMappings"
> value="refresh"/>
> +         <property name="openjpa.jdbc.MappingDefaults"
> value="DefaultMissingInfo=true"/>
> +         <property name="openjpa.RuntimeUnenhancedClasses"
> value="supported"/>
> +      </properties>
> +   </persistence-unit>
> +
>  </persistence>
>
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message