JackSonMixInAnnotations for Polymorphic Type Handling - jackson

In following code I am trying to use JackSonMixInAnnotations for Polymorphic Type Handling
but my code is not working.
Please suggest what changes I need to do, to correct this code.
I am not suppose to make any change in Animal class.Also, like Dog class I may have many classes which extend Animal class.
Code should print the class of "Animal"(either Dog or Elephant) depending on "type" field of Animal object passed to "test()" in MyController class from client.
Client may send JSON like:
"{\"id\":\"DOG\",\"type\":\"dog\",\"someAttrOfDog\":\"someValue\"}"
import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonTypeInfo;
#JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
/*#JsonSubTypes({// #JsonSubTypes.Type(value = Dog.class, name = "dog")
})*/
public abstract class Animal{
private String id;
private String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package com.Animal;
import org.codehaus.jackson.annotate.JsonTypeName;
#JsonTypeName("cat")
public class Cat extends Animal{
String someAttrOfCat;
public String getSomeAttrOfCat() {
return someAttrOfCat;
}
public void setSomeAttrOfCat(String someAttrOfCat) {
this.someAttrOfCat = someAttrOfCat;
}
}
package com.Animal;
import org.codehaus.jackson.annotate.JsonTypeName;
#JsonTypeName("dog")
public class Dog extends Animal{
private String someAttrOfDog;
public String getSomeAttrOfDog() {
return someAttrOfDog;
}
public void setSomeAttrOfDog(String someAttrOfDog) {
this.someAttrOfDog = someAttrOfDog;
}
}
package com.Animal;
import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonSubTypes.Type;
#JsonSubTypes (
{ #Type(value = Dog.class, name = "dog") }
)
public class MixinDog {
}
package com.startUpClasses;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.codehaus.jackson.map.ObjectMapper;
import com.Animal.Animal;
import com.Animal.MixinDog;
public class StartApp extends HttpServlet{
public void init() throws ServletException{
System.out.println("---------In StartApp init------------");
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().addMixInAnnotations(Animal.class, MixinDog.class);
System.out.println("---------In StartApp init1------------");
mapper.getDeserializationConfig().addMixInAnnotations(Animal.class, MixinDog.class);
System.out.println("---------In StartApp init2------------");
}
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.Animal.Animal;
#Controller
public class MyController {
#RequestMapping( value = "test",method = RequestMethod.POST)
public #ResponseBody String test(#RequestBody Animal animal){
System.out.println("In Controller");
System.out.println(animal.getClass());
return "success";
}
}
AnimalWithJsonType-servlet.xml
<context:component-scan base-package="com.restcontrollers"/>
<mvc:annotation-driven />
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>AnimalWithJsonType</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>AnimalWithJsonType</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet>
<servlet-name>StartApp</servlet-name>
<servlet-class>com.startUpClasses.StartApp</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AnimalWithJsonType</servlet-name>
<url-pattern>/animals/*</url-pattern>
</servlet-mapping>
</web-app>

Related

Rest api development: getting error: MessageBodyWriter not found for media type=application/xml

I am new to developing REST api, and trying to create a small dummy REST API.
I am using tomcat version 8.5.X. Eclipse Version: 2019-12 (4.14.0).
Below is my code.
MessageResuroce.java:
package org.vaibhavc.practice.microservice.messanger.resources;
import java.util.List;
import org.vaibhavc.practice.microservice.messanger.model.Message;
import org.vaibhavc.practice.microservice.messanger.service.MessageService;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.GenericEntity;
#Path("/messages")
public class MessageResource {
MessageService messageService = new MessageService();
#GET
#Produces(MediaType.APPLICATION_XML)
public Response getMessage() {
List<Message> newMessage = messageService.getAllMessages();
GenericEntity<List<Message>> list = new GenericEntity<List<Message>>(newMessage) {};
return Response.ok(list).build();
}
}
Message.java
package org.vaibhavc.practice.microservice.messanger.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Message {
private long id;
private String message;
private Date created;
private String author;
public Message(){
}
public Message(long id, String message, String author) {
this.id = id;
this.message = message;
this.created = new Date();
this.author = author;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
MessageService.java
package org.vaibhavc.practice.microservice.messanger.service;
import java.util.ArrayList;
import java.util.List;
import org.vaibhavc.practice.microservice.messanger.model.Message;
public class MessageService {
public List<Message> getAllMessages(){
Message m1 = new Message(1L,"Hello world!","Vaibhav");
Message m2 = new Message(2L,"Hello jersery!","Vaibhav");
List<Message> list = new ArrayList<>();
list.add(m1);
list.add(m2);
return list;
}
}
code built and compiled successfully.
When I trying to access url "http://localhost:8080/messanger/webapi/messages" I am getting error as follow:
SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=java.util.List.
Any idea what I am missing here?
Please add jersey-media-moxy library in your class path and check
Maven Code Snippet
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.31</version>

Retrofit with recyclerview issue

I am not getting data in recycler view but not getting any error .
This is Main Activity class
package in.co.getonlinerecharge.cab.bw_cab.activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.widget.TextView;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import in.co.getonlinerecharge.cab.bw_cab.AppController;
import in.co.getonlinerecharge.cab.bw_cab.R;
import in.co.getonlinerecharge.cab.bw_cab.adepter.CarTypeAdepter;
import in.co.getonlinerecharge.cab.bw_cab.helper.ToastHelper;
import in.co.getonlinerecharge.cab.bw_cab.model.Cartype;
import in.co.getonlinerecharge.cab.bw_cab.model.CartypeArray;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class Slect_Car_Activity extends AppCompatActivity {
RecyclerView rvGetCartype;
private ArrayList<Cartype> data;
private CarTypeAdepter carTypeAdepter;
private TextView txt_data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slect__car_);
rvGetCartype = (RecyclerView)findViewById(R.id.RV_list);
txt_data = (TextView)findViewById(R.id.txt_data);
getAndSetCarType();
}
private void getAndSetCarType() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage(getString(R.string.please_wait));
progressDialog.show();
Call<CartypeArray> call = AppController.getInstance().getApiInterface().getCartype();
call.enqueue(new Callback<CartypeArray>() {
#Override
public void onResponse(Call<CartypeArray> call, Response<CartypeArray> response) {
progressDialog.dismiss();
CartypeArray cartypeArray = response.body();
Collections.reverse(cartypeArray.getCtypes());
carTypeAdepter = new CarTypeAdepter(cartypeArray,getApplicationContext());
rvGetCartype.setAdapter(carTypeAdepter);
}
#Override
public void onFailure(Call<CartypeArray> call, Throwable t) {
progressDialog.dismiss();
}
});
}
}
This is my model class for retrofit which gives Json array with status
package in.co.getonlinerecharge.cab.bw_cab.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Cartype {
#SerializedName("id")
#Expose
private String id;
#SerializedName("vehicle_type")
#Expose
private String Vehicale_type;
#SerializedName("vehicle_name")
#Expose
private String Vehicale_name;
#SerializedName("vehicle_no")
#Expose
private String Vehicale_no;
#SerializedName("vimage")
#Expose
private String Vimage;
#SerializedName("status")
#Expose
private String status;
#SerializedName("created_at")
#Expose
private String created_at;
#SerializedName("updated_at")
#Expose
private String updated_at;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getVehicale_type() {
return Vehicale_type;
}
public void setVehicale_type(String vehicale_type) {
Vehicale_type = vehicale_type;
}
public String getVehicale_name() {
return Vehicale_name;
}
public void setVehicale_name(String vehicale_name) {
Vehicale_name = vehicale_name;
}
public String getVehicale_no() {
return Vehicale_no;
}
public void setVehicale_no(String vehicale_no) {
Vehicale_no = vehicale_no;
}
public String getVimage() {
return Vimage;
}
public void setVimage(String vimage) {
Vimage = vimage;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getUpdated_at() {
return updated_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
}
This is my Adapter class with view holder for recycler view
package in.co.getonlinerecharge.cab.bw_cab.adepter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
import in.co.getonlinerecharge.cab.bw_cab.R;
import in.co.getonlinerecharge.cab.bw_cab.model.Cartype;
import in.co.getonlinerecharge.cab.bw_cab.model.CartypeArray;
import in.co.getonlinerecharge.cab.bw_cab.utils.Constans;
public class CarTypeAdepter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private CartypeArray cartypeArray;
private Context mcontext;
public CarTypeAdepter(CartypeArray cartypeArray, Context mcontext) {
this.cartypeArray = cartypeArray;
this.mcontext = mcontext;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = (LayoutInflater.from(parent.getContext()).inflate(R.layout.list_car,parent, false));
CartypeHolder cartypeHolder = new CartypeHolder(view);
return cartypeHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder Holder, int position) {
CartypeHolder cartypeHolder = (CartypeHolder) Holder;
cartypeHolder.txt_cartype.setText(cartypeArray.getCtypes().get(position).getVehicale_name());
}
#Override
public int getItemCount() {
return cartypeArray.getCtypes().size();
}
private class CartypeHolder extends RecyclerView.ViewHolder {
ImageView img_car;
TextView txt_cartype;
public CartypeHolder(View itemview) {
super(itemview);
img_car = (ImageView)itemview.findViewById(R.id.CarImageView);
txt_cartype = (TextView)itemview.findViewById(R.id.titleTextView);
}
}
}
My second model class for retrofit for getting JSON data
package in.co.getonlinerecharge.cab.bw_cab.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class CartypeArray {
#SerializedName("status")
#Expose
private Boolean status;
#SerializedName("Cartype")
#Expose
private List<Cartype> ctypes;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public List<Cartype> getCtypes() {
return ctypes;
}
public void setCtypes(List<Cartype> ctypes) {
this.ctypes = ctypes;
}
}
This is Activity main XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" tools:context="in.co.getonlinerecharge.cab.bw_cab.activity.Slect_Car_Activity">
<android.support.design.widget.AppBarLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:title="Select Your Car" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/RV_list"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/txt_data"/>
</LinearLayout>
List of display data for list view
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="50dp"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="#dimen/card_height"
android:orientation="vertical"
>
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/CarImageView"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="#drawable/suv"
/>
<TextView
android:layout_gravity="center"
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="SUV"
android:textSize="#dimen/card_text_size"
android:textColor="#color/colorPrimary"/>
</LinearLayout>
</android.support.v7.widget.CardView>
set Layout Manager to your recycler in onCreate:
rvGetCartype = (RecyclerView)findViewById(R.id.RV_list);
rvGetCartype.setLayoutManager(new LinearLayoutManager(this));
If it didnt help try next:
1.Make sure, that in your response ArrayList isnt empty.
2.If it isnt, try to next:
public class CarTypeAdepter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<Cartype> cartypeArray;
private Context mcontext;
public CarTypeAdapter(Context context){
this.mcontext = context;
cartypeArray = new ArrayList<>();
}
public void setList(ArrayList<Cartype> list){
this. cartypeArray = list;
notifyDataSetChanges();
}
//other methods
}
then create variable of this adapter in activity and init it in onCreate, and set it to your recycler view. Then in onResponse use method setList(cartypeArray) to set array to adapter.
Hope you understand me and its help.

NullPointerException: Attempt to invoke virtual method 'void io.realm.Realm.beginTransaction()' on a null object reference

So I am making an app where I use an activity to introduce data about cities using Realm. I want to save the data when the floating action button is pressed but I keep getting a NullPointerExeption and when I debbug the app I see that realm in realm.beginTransaction() is null..
Can someone give an advice on why this happens? Thank you!
City class:
package com.android.bianca.cityworld2.models;
import com.android.bianca.cityworld2.app.MyApplication;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
/**
* Created by Bianca on 25/01/2017.
*/
public class City extends RealmObject {
#PrimaryKey
private int id;
#Required
private String nombre;
#Required
private String description;
#Required
private String imagen;
public City(){
};
public City(String nombre, String description, String imagen) {
this.id = MyApplication.CityID.incrementAndGet();
this.nombre = nombre;
this.description = description;
this.imagen = imagen;
}
public int getID(){ return id;}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImagen() {
return imagen;
}
public void setImagen(String imagen) {
this.imagen = imagen;
}
}
AddEditActivity:
package com.android.bianca.cityworld2.activities;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.bianca.cityworld2.R;
import com.android.bianca.cityworld2.models.City;
import com.squareup.picasso.Picasso;
import io.realm.Realm;
public class AddEditActivity extends AppCompatActivity {
private FloatingActionButton fabSave;
private Realm realm;
private TextView textViewNombre;
private TextView textViewDescription;
private ImageView imageViewImagen;
private TextView textViewUrlFoto;
private ImageView imageViewPreview;
private City ciudadNueva;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_edit);
Realm.init(getApplicationContext());
Realm realm = Realm.getDefaultInstance();
bindReferences();
imageViewPreview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String imageURL = textViewUrlFoto.getText().toString();
if(imageURL.equals("")) {
Toast.makeText(AddEditActivity.this, "No has introducido ningun url", Toast.LENGTH_SHORT).show();
}else {
Picasso.with(AddEditActivity.this).load(imageURL).error(R.mipmap.ic_star).fit().into(imageViewImagen);
}
}
});
fabSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
crearNuevaCiudad();
}
});
}
private void crearNuevaCiudad(){
String nombre = textViewNombre.getText().toString().trim();
String desc = textViewDescription.getText().toString().trim();
String img = textViewUrlFoto.getText().toString().trim();
ciudadNueva = new City(nombre,desc,img);
realm.beginTransaction();
realm.copyToRealm(ciudadNueva);
realm.commitTransaction();
//<Toast.makeText(AddEditActivity.this, nombre + "|"+description+"|"+img, Toast.LENGTH_SHORT).show();
}
private void bindReferences(){
fabSave = (FloatingActionButton) findViewById(R.id.fabSave);
textViewNombre =(TextView) findViewById(R.id.editTextEditAddNombre);
textViewDescription =(TextView) findViewById(R.id.editTextAddEditDescription);
textViewUrlFoto =(TextView) findViewById(R.id.editTextEditAddUrl);
imageViewImagen = (ImageView) findViewById(R.id.imageViewEditAddBackground);
imageViewPreview = (ImageView) findViewById(R.id.imageViewEditAddPreview);
}
}
MyApplication:
package com.android.bianca.cityworld2.app;
import android.app.Application;
import com.android.bianca.cityworld2.models.City;
import java.util.concurrent.atomic.AtomicInteger;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmObject;
import io.realm.RealmResults;
/**
* Created by Bianca on 26/01/2017.
*/
public class MyApplication extends Application {
public static AtomicInteger CityID = new AtomicInteger();
#Override
public void onCreate() {
setUpRealmConfig();
Realm realm = Realm.getDefaultInstance();
CityID = getIdByTable(realm, City.class);
realm.close();
}
private void setUpRealmConfig() {
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build();
Realm.setDefaultConfiguration(config);
}
private <T extends RealmObject> AtomicInteger getIdByTable(Realm realm, Class<T> anyClass) {
RealmResults<T> results = realm.where(anyClass).findAll();
return (results.size() > 0) ? new AtomicInteger(results.max("id").intValue()) : new AtomicInteger();
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.bianca.cityworld2">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".activities.MainActivity">
</activity>
<activity android:name=".activities.AddEditActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Moxy List<Map<String,String>> not expected marshalling

I'm trying to marshal this class:
package otherTest;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class SearchResult {
private List<Map<String,String>> listOfMap;
private Map<String,Collection<String>> mapWithList;
public List<Map<String, String>> getListOfMap() {
return listOfMap;
}
public void setListOfMap(List<Map<String, String>> listOfMap) {
this.listOfMap = listOfMap;
}
public Map<String, Collection<String>> getMapWithList() {
return mapWithList;
}
public void setMapWithList(Map<String, Collection<String>> mapWithList) {
this.mapWithList = mapWithList;
}
public SearchResult(){}
}
oxm.xml
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="otherTest"
xml-mapping-metadata-complete="true">
<java-types>
<java-type name="SearchResult">
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="listOfMap"/>
<xml-element java-attribute="mapWithList"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Demo.java
package otherTest;
import java.io.InputStream;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String , Object>();
ClassLoader classLoader = Demo.class.getClassLoader();
InputStream modelStream = classLoader.getResourceAsStream("otherTest/oxm.xml");
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, modelStream);
JAXBContext jc = JAXBContext.newInstance(new Class[] {SearchResult.class}, properties);
List<Map<String,String>> results = new ArrayList<Map<String,String>>();
Map<String,String> test = new HashMap<String,String>();
Map<String,Collection<String>> daMashalare = new HashMap<String,Collection<String>>();
test.put("id","10");
test.put("publicationTitle","20");
test.put("paginazione","boh");
test.put("pageSize", "10");
results.add(test);
Collection<String> listaString = new ArrayList<String>();
listaString.add("testlist");
daMashalare.put("nothing",listaString);
SearchResult result = new SearchResult();
result.setListOfMap(results);
result.setMapWithList(daMashalare);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(result, System.out);
}
}
Unluckly the output that I get is:
<?xml version="1.0" encoding="UTF-8"?>
<searchResult>
<listOfMap>{id=10, paginazione=boh, pageSize=10, publicationTitle=20}</listOfMap>
<mapWithList>
<entry>
<key>nothing</key>
<value>testlist</value>
</entry>
</mapWithList>
</searchResult>
So As you can see the listOfMap attribute is not how I would like to see it
<?xml version="1.0" encoding="UTF-8"?>
<searchResult>
<listOfMap>
<id>10</id>
<paginazione>boh</paginazione>
<pageSize>10</pageSize>
<publicationTitle>20</publicationTitle>
</listOfMap>
<mapWithList>
<entry>
<key>nothing</key>
<value>testlist</value>
</entry>
</mapWithList>
</searchResult>
How Can I set an adapter to solve this problem? I have also included this test package:
that you can download and test it http://bit.ly/14aWIu1
Thank you
This is a generic solution for Map:
MapAdapter<K,V>
package otherTest;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class MapAdapter<K, V> extends XmlAdapter<MapType<K, V>, Map<K, V>> {
#Override
public Map<K, V> unmarshal(MapType<K, V> v) throws Exception {
HashMap<K, V> map = new HashMap<K, V>();
for (MapEntryType<K, V> mapEntryType : v.getEntry()) {
map.put(mapEntryType.getKey(), mapEntryType.getValue());
}
return map;
}
#Override
public MapType marshal(Map<K, V> v) throws Exception {
MapType<K, V> mapType = new MapType<K, V>();
for (Map.Entry<K, V> entry : v.entrySet()) {
MapEntryType<K, V> mapEntryType = new MapEntryType<K, V>();
mapEntryType.setKey(entry.getKey());
mapEntryType.setValue(entry.getValue());
mapType.getEntry().add(mapEntryType);
}
return mapType;
}
}
MapEntryType<K,V>
package otherTest;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
#XmlAccessorType(XmlAccessType.PROPERTY)
public class MapEntryType<K, V> {
private K key;
private V value;
public MapEntryType() {
}
public MapEntryType(Map.Entry<K, V> e) {
key = e.getKey();
value = e.getValue();
}
#XmlElement
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
#XmlElement
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
MapType<K,V>
package otherTest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MapType<K, V> {
private List<MapEntryType<K, V>> entry = new ArrayList<MapEntryType<K, V>>();
public MapType() {
}
public MapType(Map<K, V> map) {
for (Map.Entry<K, V> e : map.entrySet()) {
entry.add(new MapEntryType<K, V>(e));
}
}
public List<MapEntryType<K, V>> getEntry() {
return entry;
}
public void setEntry(List<MapEntryType<K, V>> entry) {
this.entry = entry;
}
}
SearchResult
package otherTest;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class SearchResult {
private List<Map<String,String>> listOfMap;
private Map<String,Collection<String>> mapWithList;
#XmlJavaTypeAdapter(MapAdapter.class)
public List<Map<String, String>> getListOfMap() {
return listOfMap;
}
public void setListOfMap(List<Map<String, String>> listOfMap) {
this.listOfMap = listOfMap;
}
public Map<String, Collection<String>> getMapWithList() {
return mapWithList;
}
public void setMapWithList(Map<String, Collection<String>> mapWithList) {
this.mapWithList = mapWithList;
}
public SearchResult(){}
}
Test
package otherTest;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.transform.TransformerException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Test {
public static void main(String[] args) throws TransformerException, Exception {
Map<String, Object> properties = new HashMap<String, Object>();
Marshaller marshaller = null;
ClassLoader classLoader = Test.class.getClassLoader();
List<Map<String,String>> results = new ArrayList<Map<String,String>>();
Map<String,String> test = new HashMap<String,String>();
test.put("id","10");
test.put("publicationTitle","20");
test.put("paginazione","boh");
test.put("pageSize", "10");
results.add(test);
InputStream modelStream = classLoader.getResourceAsStream("test/oxm.xml");
JAXBContext ctx = null;
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, modelStream );
try {
ctx = JAXBContext.newInstance(new Class[] {SearchResult.class}, properties);
} catch (JAXBException e) {
e.printStackTrace();
}
marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
SearchResult result = new SearchResult();
result.setListOfMap(results);
marshaller.marshal(result, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<listOfMap>
<entry>
<key xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">id</key>
<value xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">10</value>
</entry>
<entry>
<key xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">paginazione</key>
<value xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">boh</value>
</entry>
<entry>
<key xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">pageSize</key>
<value xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">10</value>
</entry>
<entry>
<key xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">publicationTitle</key>
<value xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">20</value>
</entry>
</listOfMap>

Can't get Form Validation working

I was learning Struts 1.1 and trying to do some form validation with my code.
But the errors that I had described in the MessageResources.properties file do not get displayed on the JSP. I tried a lot of options but couldn't get it off the ground. I have attached some of the code.
MessageResources.properties
error.name.required = Please mention your name.
error.email.incorrect = You E-Mail ID is Incorrect.
error.phone.numericError = Phone number should consist only of digits.
error.phone.lengthIncorrect = Phone number should be only of 10 digits.
struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="detailsForm" type="com.example.form.DetailsForm"/>
</form-beans>
<action-mappings>
<action input="/detailsEntry.jsp" name="detailsForm" path="/DetailsForm" type="com.example.action.DetailsAction" validate="true">
<forward name="success" path="/displayDetails.jsp"/>
<forward name="failure" path="/failure.jsp"/>
</action>
</action-mappings>
</struts-config>
Form Class:
package com.example.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
public class DetailsForm extends ActionForm {
private String name;
private String email;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
#Override
public void reset(ActionMapping mapping, HttpServletRequest request) {
this.name = null;
this.email = null;
this.phone = null;
}
#Override
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors actionErrors = new ActionErrors();
if (this.name.equals(null) || this.name.length() == 0) {
actionErrors.add("name", new ActionError("error.name.required"));
}
return actionErrors;
}
private boolean isNumeric(String phoneNumber) {
try {
Integer.parseInt(phoneNumber);
return true;
}
catch (NumberFormatException numberFormatException) {
return false;
}
}
}
The default resource filename is ApplicationResources.properties.
Using a different (or multiple) resource files requires configuration in struts-config.xml:
<message-resource parameter="MessageResources" null="false" />
Don't forget to add the following to your jsp:
<html:errors />
Your error messages will appear where ever you put this tag on on your jsp.
And if you want your error message to be displayed next to the field they relates to then use the following:
<html:errors property="custName" />
where "custName" is the name you gave the error message when you created it in your form ex:
ActionMessages errors = new ActionMessages();
errors.add("custName", new ActionMessage("custName.invalid"));
request.setAttribute(Globals.ERROR_KEY, errors);