title: Spring Data Solr: how to set multiValue to false when declaring a field
body: <p>I am playing around with Spring Data Solr with Schemaless Solr. There are some dots I am not able to connect: when and how are the schema fields being created?</p>
  <p><a href="https://github.com/spring-projects/spring-data-solr" rel="nofollow noreferrer">The following page states</a></p>
  <blockquote>
  <p>Automatic schema population will inspect your domain types whenever the applications context is refreshed and populate new fields to your index based on the properties configuration. This requires solr to run in Schemaless Mode.</p>
  <p>Use @Indexed to provide additional details like specific solr types to use.</p>
  </blockquote>
  <p>It also goes to show a curl request:</p>
  <blockquote>
  <p>// curl ../solr/collection1/schema/fields -X POST -H 'Content-type:application/json'</p>
  </blockquote>
  <p>However, when I run a simple example with field annotated with @Indexed, I do not see the /schema/fields API being called on SOLR. How are these fields created?</p>
  <p>The reason I am asking is that they seem to be automatically created with multiValued=true. I did not see the @Indexed annotation taking multiValued as a parameter. How can I force Spring Data Solr to declare fields as non-multiValued when it creates them?</p>
  <p>Now, all of this is really to resolve this exception I am seeing.</p>
  <pre><code>java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
  at org.springframework.util.Assert.notNull(Assert.java:115)
  at org.springframework.util.Assert.notNull(Assert.java:126)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:426)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readCollection(MappingSolrConverter.java:601)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:440)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:412)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.getPropertyValue(MappingSolrConverter.java:395)
  at org.springframework.data.solr.core.convert.MappingSolrConverter.getValue(MappingSolrConverter.java:206)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:194)
  at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:186)
  at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:309)
  at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:186)
  at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:174)
  at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:149)
  at org.springframework.data.solr.core.SolrTemplate.convertSolrDocumentListToBeans(SolrTemplate.java:560)
  at org.springframework.data.solr.core.SolrTemplate.convertQueryResponseToBeans(SolrTemplate.java:552)
  at org.springframework.data.solr.core.SolrTemplate.createSolrResultPage(SolrTemplate.java:369)
  at org.springframework.data.solr.core.SolrTemplate.doQueryForPage(SolrTemplate.java:300)
  at org.springframework.data.solr.core.SolrTemplate.queryForPage(SolrTemplate.java:308)
  at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:111)
  at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:106)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at 
  </code></pre>
  <p>My guess is that the exception is happening because values are being returned as a collection?</p>
  <p>I tried to step through the code to understand what is happening. The field that is causing problem is &quot;name&quot;, the value is [product-1]. The exception is happening when trying to unmarshall a solr document into a POJO.</p>
  <p>First we go inside the following method:</p>
  <pre><code>    private &lt;T&gt; T readValue(Object value, TypeInformation&lt;?&gt; type, Object parent) {
          if (value == null) {
              return null;
          }
  
          Assert.notNull(type);
          Class&lt;?&gt; rawType = type.getType();
          if (hasCustomReadTarget(value.getClass(), rawType)) {
              return (T) convert(value, rawType);
          }
  
          Object documentValue = null;
          if (value instanceof SolrInputField) {
              documentValue = ((SolrInputField) value).getValue();
          } else {
              documentValue = value;
          }
  
          if (documentValue instanceof Collection) {
              return (T) readCollection((Collection&lt;?&gt;) documentValue, type, parent);
          } else if (canConvert(documentValue.getClass(), rawType)) {
              return (T) convert(documentValue, rawType);
          }
  
          return (T) documentValue;
  
      }
  </code></pre>
  <p>When calling this method, the value is a collection and the type is java.lang.String. This results in the if(documentValue instanceof Collection) being selected, which results into following method being executed:</p>
  <pre><code>        private Object readCollection(Collection&lt;?&gt; source, TypeInformation&lt;?&gt; type, Object parent) {
          Assert.notNull(type);
  
          Class&lt;?&gt; collectionType = type.getType();
          if (CollectionUtils.isEmpty(source)) {
              return source;
          }
  
          collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
  
          Collection&lt;Object&gt; items;
          if (type.getType().isArray()) {
              items = new ArrayList&lt;Object&gt;();
          } else {
              items = CollectionFactory.createCollection(collectionType, source.size());
          }
  
          TypeInformation&lt;?&gt; componentType = type.getComponentType();
  
          Iterator&lt;?&gt; it = source.iterator();
          while (it.hasNext()) {
              items.add(readValue(it.next(), componentType, parent));
          }
  
          return type.getType().isArray() ? convertItemsToArrayOfType(type, items) : items;
      }
  </code></pre>
  <p>In this method, we end up calling type.getComponentType(), which returns null and ultimately cause Assert.notNull() to fail.</p>
  <p>What am I missing in all this?</p>
  <p>My code is as follows. Launch and config class:</p>
  <pre><code>@Configuration
  @ComponentScan
  @EnableAutoConfiguration
  @EnableSolrRepositories(schemaCreationSupport=true, basePackages = { &quot;com.example.solrdata&quot; }, multicoreSupport = true)
  public class Application {
  
  public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
  }
  }
  </code></pre>
  <p>Model class:</p>
  <pre><code>@SolrDocument(solrCoreName = &quot;collection1&quot;)
  public class Product {
  
  @Id
  String id;
  @Indexed
  String name;
  
  public Product(String id, String name) {
      this.id = id;
      this.name = name;
  }
  
  public Product() {
      super();
  }
  
  public String getId() {
      return id;
  }
  
  public void setId(String id) {
      this.id = id;
  }
  
  public String getName() {
      return name;
  }
  
  public void setName(String name) {
      this.name = name;
  }}
  </code></pre>
  <p>Repository:</p>
  <pre><code>public interface ProductRepository extends SolrCrudRepository&lt;Product, String&gt; {}
  </code></pre>
  <p>Test class:</p>
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @SpringApplicationConfiguration(Application.class)
  public class SolrProductRepositoryTest  {
  
  @Autowired
  private ProductRepository repo;
  
  @Before @After
  public void setup(){
      repo.deleteAll();
  }
  
  @Test
  public void testCRUD() {
      assertEquals(0, repo.count());
      Product product = new Product(&quot;1&quot;,&quot;product-1&quot;);
      repo.save(product);
      assertEquals(1, repo.count());
      Product product2 = repo.findOne(product.getId());
      assertEquals(product2.getName(), product.getName());
  }}
  </code></pre>
  <p>And finally, my POM:</p>
  <pre><code>&lt;parent&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
      &lt;version&gt;1.3.3.RELEASE&lt;/version&gt;
  &lt;/parent&gt;
  
  &lt;dependencies&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
          &lt;scope&gt;test&lt;/scope&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
          &lt;artifactId&gt;spring-data-solr&lt;/artifactId&gt;
      &lt;/dependency&gt;
  &lt;/dependencies&gt;
  </code></pre>