Gwt-platform with UiBinder and UiEditors Framework (GWT Editors) - gwt

I struggle with Editor framework of gwt. Mostly because the documentation is lame- no hurt feelings- just saying.
Now I have problem that I cannot execute button event on editor. This is my error:
Uncaught com.google.gwt.event.shared.UmbrellaException: Exception caught: (TypeError) : Cannot read property 'onLoginButtonClick_3_g$' of undefined
I am not sure what I am doing wrong. I didn't found any good example of that. I hope someone will help.
Here is my code:
Editor
public class LoginEditor extends ViewWithUiHandlers<LoginEditorUiHandlers> implements Editor<LoginModel> {
private VerticalPanel widget = new VerticalPanel();
MaterialTextBox email = new MaterialTextBox();
MaterialTextBox password = new MaterialTextBox();
MaterialButton btnLogin = new MaterialButton();
public LoginEditor() {
initWidget(widget);
email.setPlaceholder("E-mail");
password.setPlaceholder("Password");
btnLogin.setText("Login");
btnLogin.addClickHandler(new ClickHandler() {
#Override public void onClick(ClickEvent event) {
onLoginButtonClick(event);
}
});
widget.add(email);
widget.add(password);
widget.add(btnLogin);
}
void onLoginButtonClick(ClickEvent e){
getUiHandlers().onLoginButtonClick();
Window.alert("TEST");
}
}
Presenter
public class LoginPresenter extends Presenter<LoginPresenter.MyView, LoginPresenter.MyProxy> implements LoginEditorUiHandlers {
public interface MyView extends View , HasUiHandlers<LoginEditorUiHandlers> {}
public static final Type<RevealContentHandler<?>> SLOT_Login = new Type<RevealContentHandler<?>>();
#ProxyStandard
#NameToken(NameTokens.login)
public interface MyProxy extends ProxyPlace<LoginPresenter> {}
// Editor
interface Driver extends SimpleBeanEditorDriver<LoginModel, LoginEditor> {}
private static final LoginService service = GWT.create(LoginService.class);
Driver editorDriver = GWT.create(Driver.class);
private LoginModel model = new LoginModel("email","pass");
private LoginEditor editor = new LoginEditor();
#Override
public void onLoginButtonClick() {
MaterialToast.fireToast("TEST");
try{
System.out.println(editorDriver == null);
System.out.println(editorDriver.isDirty());
editorDriver.isDirty();
} catch (NullPointerException e) {
MaterialToast.fireToast("Null: " + e.getLocalizedMessage());
}
if (editorDriver.isDirty()) {
model = editorDriver.flush();
if (editorDriver.hasErrors()) {
StringBuilder errorBuilder = new StringBuilder();
for (EditorError error : editorDriver.getErrors()) {
errorBuilder.append(error.getMessage() + "\n");
}
MaterialToast.fireToast(errorBuilder.toString());
} else {
service.login(
model, new MethodCallback<Integer>() {
#Override
public void onSuccess(Method method, Integer response) {
MaterialToast.fireToast("Succefully set info. status code: " + response);
}
#Override
public void onFailure(Method method, Throwable exception) {
MaterialToast.fireToast("Error setting");
}
});
}
} else {
MaterialToast.fireToast("Data has not changed");
}
}
#Inject
LoginPresenter(
EventBus eventBus,
MyView view,
MyProxy proxy) {
super(eventBus, view, proxy, RevealType.Root);
editorDriver.initialize(editor);
editorDriver.edit(model);
getView().setUiHandlers(this);
}
}
View
public class LoginView extends ViewWithUiHandlers<LoginEditorUiHandlers> implements LoginPresenter.MyView {
interface Binder extends UiBinder<Widget, LoginView> {
}
#Inject
LoginView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}
}
View.ui.xml
<m:MaterialRow ui:field="loginWidget">
<m:MaterialColumn grid="s12 m4 l4" offset="l4" >
<m:MaterialTitle title="Login" description="Please provide your account credentials."/>
<m:MaterialPanel padding="5" shadow="1" addStyleNames="{style.panel}">
<m:MaterialPanel addStyleNames="{style.fieldPanel}">
<e:LoginEditor></e:LoginEditor>
</m:MaterialPanel>
</m:MaterialPanel>
</m:MaterialColumn>
</m:MaterialRow>
UiHandlers
interface LoginEditorUiHandlers extends UiHandlers {
void onLoginButtonClick();
}
interface LoginUiHandlers extends UiHandlers {
}

Here is working solution:
Presenter
package pl.korbeldaniel.cms.client.login;
import java.util.ArrayList;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.MethodCallback;
import gwt.material.design.client.ui.MaterialToast;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.shared.GwtEvent.Type;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.annotations.ProxyStandard;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.gwtplatform.mvp.client.annotations.NameToken;
import com.gwtplatform.mvp.client.proxy.RevealContentHandler;
import com.gwtplatform.mvp.client.HasUiHandlers;
import pl.korbeldaniel.cms.client.editor.BeanEditView;
import pl.korbeldaniel.cms.client.model.LoginModel;
import pl.korbeldaniel.cms.client.place.NameTokens;
import pl.korbeldaniel.cms.client.service.LoginService;
public class LoginPresenter extends Presenter<LoginPresenter.MyView, LoginPresenter.MyProxy> implements LoginUiHandlers {
public interface MyView extends BeanEditView<LoginModel>, HasUiHandlers<LoginUiHandlers> {}
public static final Type<RevealContentHandler<?>> SLOT_Login = new Type<RevealContentHandler<?>>();
#ProxyStandard
#NameToken(NameTokens.login)
public interface MyProxy extends ProxyPlace<LoginPresenter> {}
// Editor
private SimpleBeanEditorDriver<LoginModel, ?> editorDriver;
private static final LoginService service = GWT.create(LoginService.class);
private LoginModel model = new LoginModel("","");
#Override
public void onLoginButtonClick() {
String msg = "User Pressed a button.";
GWT.log(msg);
if (editorDriver.isDirty()) {
model = editorDriver.flush();
validateModel();
GWT.log(String.valueOf(editorDriver.hasErrors()));
if (editorDriver.hasErrors()) {
MaterialToast.fireToast("Errors occur");
StringBuilder errorBuilder = new StringBuilder();
for (EditorError error : editorDriver.getErrors()) {
GWT.log(error.getMessage());
errorBuilder.append(error.getMessage() + "\n");
}
//MaterialToast.fireToast(errorBuilder.toString());
RootPanel.get().add(new Label(errorBuilder.toString()));
} else {
service.login(
model, new MethodCallback<Integer>() {
#Override
public void onSuccess(Method method, Integer response) {
MaterialToast.fireToast("Succefully set info. status code: " + response);
}
#Override
public void onFailure(Method method, Throwable exception) {
MaterialToast.fireToast("Error setting");
}
});
}
} else {
MaterialToast.fireToast("Data has not changed");
}
}
private void validateModel() {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<LoginModel>> violations = validator.validate(model);
GWT.log(String.valueOf(violations.size()));
if (violations.size() > 0) {
editorDriver.setConstraintViolations(new ArrayList<ConstraintViolation<?>>(violations));
}
}
#Inject
LoginPresenter(EventBus eventBus,MyView view, MyProxy proxy) {
super(eventBus, view, proxy, RevealType.Root);
getView().setUiHandlers(this);
editorDriver = getView().createEditorDriver();
editorDriver.edit(model);
}
}
View/Editor
package pl.korbeldaniel.cms.client.login;
import gwt.material.design.client.ui.MaterialButton;
import gwt.material.design.client.ui.MaterialCheckBox;
import gwt.material.design.client.ui.MaterialTextBox;
import javax.inject.Inject;
import pl.korbeldaniel.cms.client.model.LoginModel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Widget;
import com.gwtplatform.mvp.client.ViewWithUiHandlers;
public class LoginView extends ViewWithUiHandlers<LoginUiHandlers> implements LoginPresenter.MyView {
interface Binder extends UiBinder<Widget, LoginView> {}
/** The driver to link the proxy bean with the view. */
public interface EditorDriver extends SimpleBeanEditorDriver<LoginModel, LoginView> { }
#UiField MaterialTextBox email;
#UiField MaterialTextBox password;
#UiField MaterialButton loginButton;
#UiField MaterialCheckBox keepMeLoggedInCheckbox;
#Inject
LoginView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
addClickHandlerToLoginButton();
}
//#UiHandler("loginButton")
private void onLoginButtonClick(ClickEvent e){
getUiHandlers().onLoginButtonClick();
}
private void addClickHandlerToLoginButton() {
loginButton.addClickHandler(new ClickHandler() {
#Override public void onClick(ClickEvent event) {
onLoginButtonClick(event);
}
});
}
#Override
public SimpleBeanEditorDriver<LoginModel, ?> createEditorDriver() {
EditorDriver driver = GWT.create(EditorDriver.class);
driver.initialize(this);
return driver;
}
}
ValidatorFactory
package pl.korbeldaniel.cms.client.login;
import javax.validation.Validator;
import pl.korbeldaniel.cms.client.model.LoginModel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.validation.client.AbstractGwtValidatorFactory;
import com.google.gwt.validation.client.GwtValidation;
import com.google.gwt.validation.client.impl.AbstractGwtValidator;
public final class SampleValidatorFactory extends AbstractGwtValidatorFactory {
/**
* Validator marker for the Validation Sample project. Only the classes and
* groups listed in the {#link GwtValidation} annotation can be validated.
*/
#GwtValidation(LoginModel.class)
public interface GwtValidator extends Validator {
}
#Override
public AbstractGwtValidator createValidator() {
return GWT.create(GwtValidator.class);
}
}
UiHandlers
package pl.korbeldaniel.cms.client.login;
import com.gwtplatform.mvp.client.UiHandlers;
interface LoginUiHandlers extends UiHandlers {
void onLoginButtonClick();
}
Bean edit view interface
package pl.korbeldaniel.cms.client.editor;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.gwtplatform.mvp.client.View;
/**
* Implemented by views that edit beans.
*
* #param <B> the type of the bean
*/
public interface BeanEditView<B> extends View, Editor<B> {
/**
* #return a new {#link SimpleBeanEditorDriver} initialized to run this editor
*/
SimpleBeanEditorDriver<B, ?> createEditorDriver();
}
I hope it will help some one.

Related

How to use Shared Preference from a Button in another activity?

Im trying to implement SharedPreferences but, since this is all so new to me, Im confused on how to actually do this. I have an activity that contains Two EditTexts and a Button; those EditTtexts are subject and grade, and the button sends it to a fragment activity, which contains a Recyclerview with its cardview etc. I have no trouble getting the input and displaying it in the Recyclerview list. When I try applying the Shared Preferences to save the custom data from the recyclerview, I have no idea where I should input the code.
I tried several tutorials, and I used gson to set a saveData, but I havent been able to call the list, making my app crash.
Activity with the Button
package com.example.repomax;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Objects;
public class Binary extends AppCompatDialogFragment {
private PersonAdapter adapter;
private static final String TAG = "Binary Dialog";
public Binary(PersonAdapter adapter) {
this.adapter = adapter;
}
private void onClick(View v) {
if (classtup.getText().toString().isEmpty() || Sectiones.getText().toString().isEmpty()) {
Toast.makeText(getContext(), "Llene todos los campos", Toast.LENGTH_LONG).show();
} else {
ApplicationClass.materias.add(new Lasmaterias(classtup.getText().toString().trim(),
Sectiones.getText().toString().trim()));
adapter.addMaterias(new Lasmaterias(classtup.getText().toString().trim(),
Sectiones.getText().toString().trim()));
Toast.makeText(getContext(), "Clase Registrada", Toast.LENGTH_SHORT).show();
classtup.setText(null);
Sectiones.setText(null);
saveData();
dismiss();
}
}
public void saveData
public interface OnInputSelected {
void SendInput(String input);
}
public OnInputSelected monInputSelected;
//Widgets
private
RecyclerView.Adapter myAdapter;
TextView Title;
EditText classtup, Sectiones;
Button addud;
Planes planes;
FragmentManager fragmentManager;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_binary, container, false);
myAdapter = new PersonAdapter(getContext(), ApplicationClass.materias);
classtup = view.findViewById(R.id.classtup);
Sectiones = view.findViewById(R.id.Sectiones);
fragmentManager = getParentFragmentManager();
planes = (Planes) fragmentManager.findFragmentById(R.id.Planes);
addud = view.findViewById(R.id.addud);
addud.setOnClickListener(this::onClick);
return view;
}
}
FragmentActivity with the RecyclerView:
package com.example.repomax;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import java.util.ArrayList;
public class Planes extends Fragment {
private static final String TAG = "Planes fragment";
RecyclerView recyclerView;
RecyclerView.Adapter myAdapter;
RecyclerView.LayoutManager layoutManager;
View view;
Button fab;
public Planes() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_planes, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this.getActivity());
recyclerView.setLayoutManager(layoutManager);
myAdapter = new PersonAdapter(getContext(), ApplicationClass.materias);
recyclerView.setAdapter(myAdapter);
fab = view.findViewById(R.id.fab);
fab.setOnClickListener(v -> {
Log.d(TAG, "onClick: Abriendo Ventanilla");
Binary dialog = new Binary((PersonAdapter) myAdapter);
dialog.setTargetFragment(Planes.this, 1);
dialog.show(getParentFragmentManager(), "Binary");
});
}
}
And finally the adapter:
package com.example.repomax;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> {
private ArrayList<Lasmaterias> materias;
private Context context;
private PersonAdapter adapter;
public PersonAdapter(Context context, ArrayList<Lasmaterias> list) {
this.context = context;
this.materias = list;
}
public void addMaterias(Lasmaterias lasmaterias) {
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvGroup;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
tvGroup = itemView.findViewById(R.id.TvPass);
itemView.setOnClickListener(v -> {
});
}
}
#NonNull
#Override
public PersonAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.class_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PersonAdapter.ViewHolder viewHolder, int position) {
viewHolder.itemView.setTag(materias.get(position));
viewHolder.tvName.setText(materias.get(position).getName());
viewHolder.tvGroup.setText(materias.get(position).getTelNr());
}
#Override
public int getItemCount() {
return materias.size();
}
}

Pointcut matching an annotation's parameter value

Suppose I have an annotation as following:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface DBOperation
{
boolean isReadOperation() default true;
}
Then in the Aspect, how could I want to write two pointcuts, one for all the method annotated with #DBOperation(isReadOperation=true) and one for #DBOperation(isReadOperation=false)?
The syntax is actually pretty straightforward. Here is an MCVE:
Marker annotation:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target(METHOD)
public #interface DBOperation {
boolean isReadOperation() default true;
}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.doSomething();
application.readValue("name");
application.writeValue("name", "John Doe");
}
public void doSomething() {}
#DBOperation
public int readValue(String fieldName) {
return 11;
}
#DBOperation(isReadOperation = false)
public String writeValue(String fieldName, Object value) {
return "dummy";
}
}
Aspect:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class DBOperationAspect {
#Before("execution(#de.scrum_master.app.DBOperation(isReadOperation=true) * *(..))")
public void interceptRead(JoinPoint joinPoint) throws Throwable {
System.out.println("Read operation: " + joinPoint);
}
#Before("execution(#de.scrum_master.app.DBOperation(isReadOperation=false) * *(..))")
public void interceptWrite(JoinPoint joinPoint) throws Throwable {
System.out.println("Write operation: " + joinPoint);
}
}
Console log:
Read operation: execution(int de.scrum_master.app.Application.readValue(String))
Write operation: execution(String de.scrum_master.app.Application.writeValue(String, Object))

Why #Autowired not working all the time?

Im trying to setup mongodb with SpringBoot and im not using context.xml but trying to configure with configuration class and annotations.
package com.configuration;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
#Configuration
#EnableMongoRepositories(basePackages = "com.mongo")
public class MongoConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "mongodbname";
}
#Override
public Mongo mongo() throws Exception {
return new MongoClient("127.0.0.1", 27017);
}
#Override
protected String getMappingBasePackage() {
return "com.mongo";
}
}
My repository looks like this :
package com.mongo.repositories;
import com.mongo.documents.Sequence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository("sequenceRepository")
public class SequenceRepository{
#Autowired
private MongoTemplate mongoTemplate;
public Sequence findOne(Query query){
return this.mongoTemplate.findOne(query,Sequence.class);
}
public List<Sequence> find(Query query){
return this.mongoTemplate.find(query,Sequence.class);
}
public void save(Sequence object){
this.mongoTemplate.save(object);
}
public void delete(Sequence object){
this.mongoTemplate.remove(object);
}
}
If i use like this in the rest controller it is working properly :
package com.controllers;
import com.mongo.documents.Sequence;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
sequenceRepository.save(sequence);
return "index";
}
}
But if i want to use the SequenceRepository inside the Sequence document like this :
package com.mongo.documents;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
public class Sequence {
#Autowired
private SequenceRepository sequenceRepository;
#Id
private String id;
private String className;
private int actual;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public int getActual() {
return actual;
}
public void setActual(int actual) {
this.actual = actual;
}
public void save(){
this.sequenceRepository.save(this);
}
public void delete(){
this.sequenceRepository.delete(this);
}
}
After that I change the code in the controller to :
package com.controllers;
import com.mongo.documents.Sequence;
import com.mongo.repositories.SequenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
sequence.save();
return "index";
}
}
I got a nullPointerExceeption at this point in the save() method.
There is no need to inject your Repository inside your Domain object Sequence as it is really bad design to have a dependency between the domain objects and your repository classes.
To follow some good practices, your Service classes or if you don't need a Service layer, your Controller classes should inject your Repository beans.
In your last code snippet your are already doing it, but the .save() method should be called on your repository SequenceRepository and not on the domain object Sequence.
An example could be the following:
#RestController
public class IndexController {
#Autowired
private SequenceRepository sequenceRepository;
#RequestMapping("/")
public String index(){
Sequence sequence = new Sequence();
sequence.setClassName("class.Test");
sequence.setActual(1);
// now let's save it
sequenceRepository.save(sequence);
return "index";
}
}
You can only autowire Spring-managed components into other Spring-managed components. Your sequence object is not a component (not annotated with #Component, #Service, #Repository or #Controller etc.)
I suggest you follow rieckpil's advice.

Getting error "No serializer found for class org.springframework.data.mongodb.core.convert.DefaultDbRefResolver$LazyLoadingInterceptor"

I am using spring data mongodb,after doing lazy loading true i am getting error "No serializer found for class org.springframework.data.mongodb.core.convert.DefaultDbRefResolver$LazyLoadingInterceptor".
My domain class is
public class Preference extends BaseEntity {
#DBRef(lazy = true)
User user;
MetadataEnum preferenceType;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public MetadataEnum getPreferenceType() {
return preferenceType;
}
public void setPreferenceType(MetadataEnum preferenceType) {
this.preferenceType = preferenceType;
}
public List<Subtype> getSubtypes() {
return subtypes;
}
public void setSubtypes(List<Subtype> subtypes) {
this.subtypes = subtypes;
}
List<Subtype> subtypes = new ArrayList<Subtype>();
boolean enableSearch;
}
i have wasted my time alot,but i am unable to get suitable answer of it? anyone can help me to reslove it?
Thanks in advance
Add this configuration code for your requirement
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.convert.LazyLoadingProxy;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
#Configuration
public class LazyLoadingSerializationConfig {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper om = new ObjectMapper();
final SimpleModule module = new SimpleModule("<your entity>", new Version(1, 0, 0,null));
module.addSerializer(LazyLoadingProxy.class, new LazyLoadingSerializer());
om.registerModule(module);
return om;
}
}
and
import java.io.IOException;
import org.springframework.data.mongodb.core.convert.LazyLoadingProxy;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class LazyLoadingSerializer extends JsonSerializer<LazyLoadingProxy> {
#Override
public void serialize(LazyLoadingProxy value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("id", value.toDBRef().getId().toString());
jgen.writeEndObject();
}
}
Hope this may help you!
switch off serializer for that bean because lazy loading with #DBRef works for list of entity only , jackson automatically serialize the #DBRef(lazy = true) List user but not for '#DBRef(lazy = true) User user. So you have to serialize it mannually or switch off serializer for that bean'.

Customized itemreader throwing ReaderNotOpenException

I have a customized item reader as shown below
class MyReader implements ItemReader<MyBean>, ItemStream{
SingleItemPeekableItemReader<MyBean> myBeanPeekableReader;
public SingleItemPeekableItemReader<MyBean> getMyBeanPeekableReader() {
return myBeanPeekableReader;
}
public void setMyBeanPeekableReader(
SingleItemPeekableItemReader<MyBean> myBeanPeekableReader) {
this.myBeanPeekableReader = myBeanPeekableReader;
}
#Resource
public void caller(ItemReader<MyBean> myJdbcReader){
myBeanPeekableReader.setDelegate(myJdbcReader);
}
#Override
public void close() throws ItemStreamException {
myBeanPeekableReader.close();
}
#Override
public void open(ExecutionContext arg0) throws ItemStreamException {
myBeanPeekableReader.open(arg0);
}
#Override
public void update(ExecutionContext arg0) throws ItemStreamException {
// TODO Auto-generated method stub
}
Class extending JdbcCursorItemReader:
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
#Component("myJdbcReader")
public class MyJdbcReader extends JdbcCursorItemReader<MyBean> {
private String sql = "Select * from mytable";
MyJdbcReader(){
super.setSql(sql);
}
#Override
#Resource
public void setDataSource(DataSource dataSource){
super.setDataSource(dataSource);
}
#Override
#Resource
public void setRowMapper(RowMapper myRowMapper){
super.setRowMapper(myRowMapper);
}
#Override
#Resource
public void setPreparedStatementSetter(PreparedStatementSetter myPrepSetter){
super.setPreparedStatementSetter(myPrepSetter);
}
}
Even after implementing ItemStream it is throwing exception ReaderNotFound..can someone suggest where I am getting wrong.