I want to create a content fragment instance, but setting an array of field paths is not working.
the code is creating the fragment and all other fields are being set correctly, but when I try and set a multi field fragment reference it isn't setting the value.
An example I followed had this code:
private void setField(ContentFragment newFragment, String field, Object value) throws ContentFragmentException {
ContentElement element = newFragment.getElement(field);
String contentType = element.getContentType();
if (value instanceof String) {
element.setContent((String) value, contentType);
} else if (value instanceof String[]) {
String[] values = (String[]) value;
element.setContent(String.join(",", values), contentType);
}
}
However all that gets set is the first element of the array with a string concatenation.
I tried changing it to
private void setField(ContentFragment newFragment, String field, Object value) throws ContentFragmentException {
ContentElement element = newFragment.getElement(field);
String contentType = element.getContentType();
if (value instanceof String) {
element.setContent((String) value, contentType);
} else if (value instanceof String[]) {
FragmentData data = element.getValue();
if (data != null) {
data.setValue(value);
}
}
}
But this failed to set a value.
I have checked the fragmentData with:
System.out.println(data.getContentType()+":"+data.getDataType().isMultiValue());
and it outputs text/plain:true
Solved! Go to Solution.
Views
Replies
Total Likes
Hi @taggatmerkle ,
Sorry for late reply. Yes OOTB is string. But we created custom datatype to allow String[].
Here is the snippet
String[] test = new String[]{"test2", "test3", "test25"};
Optional.ofNullable(slingRequest.getResourceResolver().getResource("/content/dam/web/qa/mynav"))
.map(cf -> cf.adaptTo(ContentFragment.class))
.map(cf -> cf.getElement("testMultiStringProperty"))
.ifPresent(ele -> {
try {
MultiValuedFragmentData data = new MultiValuedFragmentData();
data.setValue(test);
ele.setValue(data);
} catch (ContentFragmentException e) {
LOG.error(e.getMessage(), e);
}
});
Here MultiValuedFragmentData class is
package com.my.core.data;
import java.util.Calendar;
import com.adobe.cq.dam.cfm.DataType;
import com.adobe.cq.dam.cfm.FragmentData;
public class MultiValuedFragmentData implements FragmentData {
private Object value;
private String contentType;
private Calendar lastModified;
private String lastModifiedBy;
@Override
public DataType getDataType() {
return new MultiStringDataType();
}
@Override
public <T> T getValue(Class<T> var1) {
return var1.cast(value);
}
@Override
public boolean isTypeSupported(Class var1) {
return true;
}
@Override
public Object getValue() {
return value;
}
@Override
public void setValue(Object var1) {
this.value = var1;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public void setContentType(String var1) {
this.contentType = var1;
}
@Override
public Calendar getLastModified() {
return lastModified;
}
@Override
public String getLastModifiedBy() {
return lastModifiedBy;
}
}
and MultiStringDataType is
package com.my.core.data;
import com.adobe.cq.dam.cfm.DataType;
public class MultiStringDataType implements DataType {
@Override
public String getValueType() {
return String[].class.getName();
}
@Override
public String getSemanticType() {
return "multi-string";
}
@Override
public boolean isMultiValue() {
return true;
}
@Override
public String getTypeString() {
return "String[]";
}
}
When I call the first method from a servlet, it produced this output
Hope this helps.
element.setContent requires 2 params. You must set as
element.setContent(values, contentType); // values is String[]
Views
Replies
Total Likes
element.setContent only accepts a string. this works fine for standard content.
I have done a workaround
private void setField(ContentFragment newFragment, String field, Object value) throws ContentFragmentException {
ContentElement element = newFragment.getElement(field);
String contentType = element.getContentType();
if (value instanceof String) {
element.setContent((String) value, contentType);
} else if (value instanceof String[]) {
element.getValue().setValue(value);
ModifiableValueMap mvm =newFragment.adaptTo(Resource.class).getChild("jcr:content/data/master").adaptTo(ModifiableValueMap.class);
mvm.put(field, value);
}
}
While this works, it is messy and I would prefer to be using the ContentElement or FragmentData, but can't get that to save the value
Views
Replies
Total Likes
Hi @taggatmerkle ,
Sorry for late reply. Yes OOTB is string. But we created custom datatype to allow String[].
Here is the snippet
String[] test = new String[]{"test2", "test3", "test25"};
Optional.ofNullable(slingRequest.getResourceResolver().getResource("/content/dam/web/qa/mynav"))
.map(cf -> cf.adaptTo(ContentFragment.class))
.map(cf -> cf.getElement("testMultiStringProperty"))
.ifPresent(ele -> {
try {
MultiValuedFragmentData data = new MultiValuedFragmentData();
data.setValue(test);
ele.setValue(data);
} catch (ContentFragmentException e) {
LOG.error(e.getMessage(), e);
}
});
Here MultiValuedFragmentData class is
package com.my.core.data;
import java.util.Calendar;
import com.adobe.cq.dam.cfm.DataType;
import com.adobe.cq.dam.cfm.FragmentData;
public class MultiValuedFragmentData implements FragmentData {
private Object value;
private String contentType;
private Calendar lastModified;
private String lastModifiedBy;
@Override
public DataType getDataType() {
return new MultiStringDataType();
}
@Override
public <T> T getValue(Class<T> var1) {
return var1.cast(value);
}
@Override
public boolean isTypeSupported(Class var1) {
return true;
}
@Override
public Object getValue() {
return value;
}
@Override
public void setValue(Object var1) {
this.value = var1;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public void setContentType(String var1) {
this.contentType = var1;
}
@Override
public Calendar getLastModified() {
return lastModified;
}
@Override
public String getLastModifiedBy() {
return lastModifiedBy;
}
}
and MultiStringDataType is
package com.my.core.data;
import com.adobe.cq.dam.cfm.DataType;
public class MultiStringDataType implements DataType {
@Override
public String getValueType() {
return String[].class.getName();
}
@Override
public String getSemanticType() {
return "multi-string";
}
@Override
public boolean isMultiValue() {
return true;
}
@Override
public String getTypeString() {
return "String[]";
}
}
When I call the first method from a servlet, it produced this output
Hope this helps.
Views
Likes
Replies
Views
Likes
Replies