### Question:
CrudUtils { @NonNull public static <S, T> T copyNonNullProperties(@NonNull final S source, @NonNull final T target, String... ignoredProperties) throws BeansException { Class<?> targetClass = target.getClass(); PropertyDescriptor[] targetProperties = getPropertyDescriptors(targetClass); List<String> ignoreList = (ignoredProperties != null ? Arrays.asList(ignoredProperties) : null); for (PropertyDescriptor targetProperty : targetProperties) { Method targetPropSetter = targetProperty.getWriteMethod(); String targetPropName = targetProperty.getName(); if (targetPropSetter != null && (ignoreList == null || !ignoreList.contains(targetPropName))) { PropertyDescriptor sourceProperty = getPropertyDescriptor(source.getClass(), targetPropName); if (sourceProperty != null) { Method sourcePropGetter = sourceProperty.getReadMethod(); if (sourcePropGetter != null && ClassUtils.isAssignable(targetPropSetter.getParameterTypes()[0], sourcePropGetter.getReturnType())) { try { if (!Modifier.isPublic(sourcePropGetter.getDeclaringClass().getModifiers())) { sourcePropGetter.setAccessible(true); } Object value = sourcePropGetter.invoke(source); if (value != null) { if (!Modifier.isPublic(targetPropSetter.getDeclaringClass().getModifiers())) { targetPropSetter.setAccessible(true); } targetPropSetter.invoke(target, value); } } catch (Throwable ex) { throw new FatalBeanException("Could not copy property '" + targetPropName + "' from source to target", ex); } } } } } return target; }  @NonNull static T copyNonNullProperties(@NonNull final S source, @NonNull final T target, String... ignoredProperties); @NonNull static String firstWordOf(@NonNull final String camelCaseString); @NonNull static String toSnakeCase(@NonNull final String camelCaseString); @NonNull static String[] splitCamelCase(@NonNull final String camelCaseString);  }### Answer:
@Test public void copyNonNullProperties() { String[] ignoreProperties = new String[]{"id", "version", "createdAt", "updatedAt"}; Model source = Model.builder() .id(1) .version(0) .createdAt(Instant.now()) .updatedAt(Instant.now()) .text("text") .build(); Model target = Model.builder().build(); Model result = CrudUtils.copyNonNullProperties(source, target, ignoreProperties); System.out.println(result); assertThat(result).isEqualTo(target); assertThat(result.getId()).isNull(); assertThat(result.getVersion()).isNull(); assertThat(result.getCreatedAt()).isNull(); assertThat(result.getUpdatedAt()).isNull(); assertThat(result.getText()).isEqualTo("text"); Model2 source2 = Model2.builder() .text("updated") .build(); Model2 target2 = Model2.builder() .id(1) .version(0) .text("text") .build(); Model2 result2 = CrudUtils.copyNonNullProperties(source2, target2, ignoreProperties); System.out.println(result2); assertThat(result2).isEqualTo(target2); assertThat(result2.getId()).isEqualTo(1); assertThat(result2.getVersion()).isEqualTo(0); assertThat(result2.getText()).isEqualTo("updated"); }