How to set up custom role provider in keycloak 18.0.2? - java

I want that user roles uploaded from db in keycloak. I have wrote RoleSPI for this, but roles don't load. My role-provider is displayed on server info.
I
I created CustomRoleProvider:
public class CustomRoleProvider implements RoleProvider {
#Override
public RoleModel addRealmRole(RealmModel realmModel, String s, String s1) {
return null;
}
#Override
public Stream<RoleModel> getRealmRolesStream(RealmModel realmModel, Integer integer, Integer integer1) {
return null;
}
#Override
public Stream<RoleModel> getRolesStream(RealmModel realmModel, Stream<String> stream, String s, Integer integer, Integer integer1) {
return null;
}
#Override
public boolean removeRole(RoleModel roleModel) {
return false;
}
#Override
public void removeRoles(RealmModel realmModel) {
}
#Override
public RoleModel addClientRole(ClientModel clientModel, String s, String s1) {
return null;
}
#Override
public Stream<RoleModel> getClientRolesStream(ClientModel clientModel, Integer integer, Integer integer1) {
return null;
}
#Override
public void removeRoles(ClientModel clientModel) {
}
#Override
public void close() {
}
#Override
public RoleModel getRealmRole(RealmModel realmModel, String s) {
System.out.println("getRealmRole()");
return roleModel;
}
#Override
public RoleModel getRoleById(RealmModel realmModel, String s) {
System.out.println("getRoleById()");
return roleModel;
}
#Override
public Stream<RoleModel> searchForRolesStream(RealmModel realmModel, String s, Integer integer, Integer integer1) {
System.out.println("searchForRolesStream()");
return roleModelStream;
}
#Override
public RoleModel getClientRole(ClientModel clientModel, String s) {
System.out.println("getClientRole()");
return roleModel;
}
#Override
public Stream<RoleModel> searchForClientRolesStream(ClientModel clientModel, String s, Integer integer, Integer integer1) {
System.out.println("searchForClientRolesStream()");
return roleModelStream;
}
}
My CustomRoleProviderFactory:
public class CustomRoleProviderFactory implements RoleProviderFactory {
#Override
public RoleProvider create(KeycloakSession keycloakSession) {
System.out.println("create");
return new CustomRoleProvider();
}
#Override
public void init(Config.Scope scope) {
}
#Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
#Override
public void close() {
}
#Override
public String getId() {
return "role-provider";
}
}
I noticed that the create method was not called after the start of keycloak.
There is org.keycloak.models.RoleProviderFactory in resources\META-INF\services packages:
com.healthec.keycloak.provider.CustomRoleProviderFactory
Do you have any ideas why roles don't loaded?

Related

Implementing a kotlin interface in java

So, after this question where I basically exploits reflection for passing primitive references to modify the primitive itself, like:
_begin("Another Window", ::showAnotherWindow)
I was looking for something to make something similar possible also from java, where at the moment I am using plains primitive arrays:
private boolean[] showAnotherWindow = {false};
imgui.begin("Another Window", showAnotherWindow);
#hotkey suggested me the possibility to create a class implementing the KMutableProperty0 interface and that automatically gets and sets the corresponding variable
Example:
KMutableProperty0<Boolean> prop =
PropUtils.javaProp(this, t -> t.showAnotherWindow, (t, r) -> { t.showAnotherWindow = r; });
_begin("Another Window", prop);
So, I wanted to give it a try and implemented the following in java.
Getter:
#FunctionalInterface
public interface Getter<T> {
T get();
}
Setter:
#FunctionalInterface
public interface Setter<T> {
void set(T type);
}
And then the class itself (I just wrote the constructor, all the methods are those requested by the interface and automatically implemented by the IDE) :
public class JavaProp <T> implements KMutableProperty0<T> {
private imgui.Getter<T> getter;
private imgui.Setter<T> setter;
public JavaProp(imgui.Getter<T> getter, imgui.Setter<T> setter) {
this.getter = getter;
this.setter = setter;
}
#Override
public void set(T t) {
setter.set(t);
}
#NotNull
#Override
public Setter<T> getSetter() {
return null;
}
#Override
public T get() {
return getter.get();
}
#Nullable
#Override
public Object getDelegate() {
return null;
}
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
#Override
public T invoke() {
return null;
}
#Override
public boolean isLateinit() {
return false;
}
#Override
public boolean isConst() {
return false;
}
#NotNull
#Override
public String getName() {
return null;
}
#NotNull
#Override
public List<KParameter> getParameters() {
return null;
}
#NotNull
#Override
public KType getReturnType() {
return null;
}
#NotNull
#Override
public List<KTypeParameter> getTypeParameters() {
return null;
}
#Override
public T call(Object... objects) {
return null;
}
#Override
public T callBy(Map<KParameter, ?> map) {
return null;
}
#Nullable
#Override
public KVisibility getVisibility() {
return null;
}
#Override
public boolean isFinal() {
return false;
}
#Override
public boolean isOpen() {
return false;
}
#Override
public boolean isAbstract() {
return false;
}
#NotNull
#Override
public List<Annotation> getAnnotations() {
return null;
}
}
But whenever I try to run that, I get the following:
Error:(45, 12) java: reference to Getter is ambiguous
both interface kotlin.reflect.KProperty0.Getter in kotlin.reflect.KProperty0 and interface kotlin.reflect.KProperty.Getter in kotlin.reflect.KProperty match
The problematic function is this one:
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
And the relevant file is kotlin.reflect.KProperty.tk, you can find it here
Any idea how could I solve it?
Just specify which interface you mean:
public KProperty0.Getter<T> getGetter()
But I would prefer to implement the class in Kotlin and only consume it from Java.

GWT - How to change NumberConstants in NumberFormat

I need to change NaN value and Minus sign in NumberFormat's NumberConstants.
It's impossible to change NumberConstants "on the fly", so I decided to subclass NumberFormat.
NumberFormat's constructor annotation says:
#param numberConstants the locale-specific number constants to use for
this format -- NOTE subclasses passing their own instance here
should pay attention to {#link #forcedLatinDigits()} and remap
localized symbols using {#link #createLatinNumberConstants(NumberConstants)}
It seemes what I should call setForcedLatinDigits(true) in order method createLatinNumberConstants(NumberConstants) to be executed. Then localized constants will be updated by that (createLatinNumberConstants) method, and I will get NumberConstants which I need.
Here is my code:
public class MyNumberFormat extends NumberFormat {
protected MyNumberFormat(String pattern, CurrencyData cdata, boolean userSuppliedPattern) {
this(defaul, pattern, cdata, userSuppliedPattern);
}
protected MyNumberFormat(NumberConstants numberConstants, String pattern, CurrencyData cdata, boolean userSuppliedPattern) {
super(numberConstants, pattern, cdata, userSuppliedPattern);
}
public static MyNumberFormat getFormat(String pattern) {
return new MyNumberFormat(pattern, CurrencyList.get().getDefault(), true);
}
protected static NumberConstants createLatinNumberConstants(
final NumberConstants orig) {
final String groupingSeparator = remapSeparator(
orig.groupingSeparator());
final String decimalSeparator = remapSeparator(
orig.decimalSeparator());
final String monetaryGroupingSeparator = remapSeparator(
orig.monetaryGroupingSeparator());
final String monetarySeparator = remapSeparator(
orig.monetarySeparator());
return new NumberConstants() {
#Override
public String currencyPattern() {
return orig.currencyPattern();
}
#Override
public String decimalPattern() {
return orig.decimalPattern();
}
#Override
public String decimalSeparator() {
return decimalSeparator;
}
#Override
public String defCurrencyCode() {
return orig.defCurrencyCode();
}
#Override
public String exponentialSymbol() {
return orig.exponentialSymbol();
}
#Override
public String globalCurrencyPattern() {
return orig.globalCurrencyPattern();
}
#Override
public String groupingSeparator() {
return groupingSeparator;
}
#Override
public String infinity() {
return orig.infinity();
}
#Override
public String minusSign() {
return UnicodeSymbols.MINUS;
}
#Override
public String monetaryGroupingSeparator() {
return monetaryGroupingSeparator;
}
#Override
public String monetarySeparator() {
return monetarySeparator;
}
#Override
public String notANumber() {
return "?";
}
#Override
public String percent() {
return orig.percent();
}
#Override
public String percentPattern() {
return orig.percentPattern();
}
#Override
public String perMill() {
return orig.perMill();
}
#Override
public String plusSign() {
return orig.plusSign();
}
#Override
public String scientificPattern() {
return orig.scientificPattern();
}
#Override
public String simpleCurrencyPattern() {
return orig.simpleCurrencyPattern();
}
#Override
public String zeroDigit() {
return "0";
}
};
}
}
So in order to format number i will execute this:
String fmt(final Double x){
MyNumberFormat.setForcedLatinDigits(true);
MyNumberFormat format = MyNumberFormat.getFormat("0.0000");
return format.format(x)
}
But in fact createLatinNumberConstants is protected static method and it can't be overriden or substituted.
So MyNumberFormat.createLatinNumberConstants() is never executed.
What am I doing wrong?
I think you do not need to overwrite createLatinNumberConstants - instead you pass your number constants to the constructor of the super class.
as a base you can use the default number constants of NumberFormat.
Something like that should work:
public class MyNumberFormat extends NumberFormat {
protected MyNumberFormat(String pattern, CurrencyData cdata, boolean userSuppliedPattern) {
super(createMyNumberConstants(NumberFormat.defaultNumberConstants), pattern, cdata, userSuppliedPattern);
}
public static MyNumberFormat getFormat(String pattern) {
return new MyNumberFormat(pattern, CurrencyList.get().getDefault(), true);
}
protected static final NumberConstants createMyNumberConstants(
final NumberConstants orig) {
return new NumberConstants() {
#Override
public String currencyPattern() {
return orig.currencyPattern();
}
#Override
public String decimalPattern() {
return orig.decimalPattern();
}
#Override
public String decimalSeparator() {
return decimalSeparator();
}
#Override
public String defCurrencyCode() {
return orig.defCurrencyCode();
}
#Override
public String exponentialSymbol() {
return orig.exponentialSymbol();
}
#Override
public String globalCurrencyPattern() {
return orig.globalCurrencyPattern();
}
#Override
public String groupingSeparator() {
return orig.groupingSeparator();
}
#Override
public String infinity() {
return orig.infinity();
}
#Override
public String minusSign() {
return orig.minusSign();
}
#Override
public String monetaryGroupingSeparator() {
return orig.monetaryGroupingSeparator();
}
#Override
public String monetarySeparator() {
return orig.monetarySeparator();
}
#Override
public String notANumber() {
return "?";
}
#Override
public String percent() {
return orig.percent();
}
#Override
public String percentPattern() {
return orig.percentPattern();
}
#Override
public String perMill() {
return orig.perMill();
}
#Override
public String plusSign() {
return orig.plusSign();
}
#Override
public String scientificPattern() {
return orig.scientificPattern();
}
#Override
public String simpleCurrencyPattern() {
return orig.simpleCurrencyPattern();
}
#Override
public String zeroDigit() {
return "0";
}
};
}

Mocking a servlet, How do I go about mocking this correctly?

Im having trouble testing this.
the line
ServletContext servletContext = getServletContext();
is giving me grief, should this be mocked and if so how would I go about it?
The error im getting is from it is.
java.lang.IllegalStateException: ServletConfig has not been initialized
My code is
public class StockSearchServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String dateOut = "yyyy/MM/dd";
DateTimeFormatter ldtf = DateTimeFormat.forPattern(dateOut);
String symbol = request.getParameter("symbol");
String from = request.getParameter("from");
DateTime fromDate = new DateTime(ldtf.parseDateTime(from));
String until = request.getParameter("until");
DateTime untilDate = new DateTime(ldtf.parseDateTime(until));
String interval = request.getParameter("interval");
HttpSession session = request.getSession();
StockQuery stockQuery = null;
try {
stockQuery = new StockQuery(symbol,from,until);
stockQuery.setInterval(interval);
} catch (ParseException ex) {
Logger.getLogger(StockSearchServlet.class.getName()).log(Level.SEVERE, null, ex);
}
session.setAttribute("stockQuery", stockQuery);
StockService stockService = ServiceFactory.getStockServiceInstance();
List<StockQuote> quotes = new ArrayList<StockQuote>();
StringBuilder stringBuilder = new StringBuilder();
try {
quotes = stockService.getQuote(symbol,fromDate, untilDate ,StockService.getIntervalEnum(interval));
} catch (StockServiceException ex) {
Logger.getLogger(StockSearchServlet.class.getName()).log(Level.SEVERE, null, ex);
}
for (StockQuote stockQuote : quotes) {
stringBuilder.append("<br>"+ stockQuote.getSymbol() + " " + stockQuote.getPrice() + " " + stockQuote.getDate());
}
String outputStockString = stringBuilder.toString();
session.setAttribute("outputStockString", outputStockString);
ServletContext servletContext = getServletContext();
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/stockquoteResults.jsp");
dispatcher.forward(request, response);
}
This is my current test im using
#Test
public void testDoPost() throws IOException, ServletException {
String symbol = "GOOG";
String from = "2015/10/05";
String until = "2015/10/09";
String interval = "day";
StockSearchServlet stockSearchServlet = new StockSearchServlet();
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getParameter("symbol")).thenReturn(symbol);
when(request.getParameter("from")).thenReturn(from);
when(request.getParameter("until")).thenReturn(until);
when(request.getParameter("interval")).thenReturn(interval);
when(request.getSession()).thenReturn(new MySession());
HttpServletResponse response = mock(HttpServletResponse.class);
//when(request.getSession()).thenReturn(new MySession());
new StockSearchServlet().doPost(request, response);
//stockSearchServlet.doPost(request, response);
String outputString = (String) request.getSession().getAttribute("outputStockString");
assertEquals("verify state", outputString.length(), 1);
}
and this class is part of the test class.
class MySession implements HttpSession {
private Map<String, Object> attributes = new HashMap<String, Object>();
#Override
public long getCreationTime() {
return 0;
}
#Override
public String getId() {
return null;
}
#Override
public long getLastAccessedTime() {
return 0;
}
#Override
public ServletContext getServletContext() {
return new ServletContext() {
#Override
public String getContextPath() {
return null;
}
#Override
public ServletContext getContext(String s) {
return null;
}
#Override
public int getMajorVersion() {
return 0;
}
#Override
public int getMinorVersion() {
return 0;
}
#Override
public int getEffectiveMajorVersion() {
return 0;
}
#Override
public int getEffectiveMinorVersion() {
return 0;
}
#Override
public String getMimeType(String s) {
return null;
}
#Override
public Set<String> getResourcePaths(String s) {
return null;
}
#Override
public URL getResource(String s) throws MalformedURLException {
return null;
}
#Override
public InputStream getResourceAsStream(String s) {
return null;
}
#Override
public RequestDispatcher getRequestDispatcher(String s) {
return new RequestDispatcher() {
#Override
public void forward(ServletRequest servletRequest, ServletResponse servletResponse)
throws ServletException, IOException {
}
#Override
public void include(ServletRequest servletRequest, ServletResponse servletResponse)
throws ServletException, IOException {
}
};
}
#Override
public RequestDispatcher getNamedDispatcher(String s) {
return null;
}
#Override
public Servlet getServlet(String s) throws ServletException {
return null;
}
#Override
public Enumeration<Servlet> getServlets() {
return null;
}
#Override
public Enumeration<String> getServletNames() {
return null;
}
#Override
public void log(String s) {
}
#Override
public void log(Exception e, String s) {
}
#Override
public void log(String s, Throwable throwable) {
}
#Override
public String getRealPath(String s) {
return null;
}
#Override
public String getServerInfo() {
return null;
}
#Override
public String getInitParameter(String s) {
return null;
}
#Override
public Enumeration<String> getInitParameterNames() {
return null;
}
#Override
public boolean setInitParameter(String s, String s1) {
return false;
}
#Override
public Object getAttribute(String s) {
return null;
}
#Override
public Enumeration<String> getAttributeNames() {
return null;
}
#Override
public void setAttribute(String s, Object o) {
}
#Override
public void removeAttribute(String s) {
}
#Override
public String getServletContextName() {
return null;
}
#Override
public ServletRegistration.Dynamic addServlet(String s, String s1) {
return null;
}
#Override
public ServletRegistration.Dynamic addServlet(String s, Servlet servlet) {
return null;
}
#Override
public ServletRegistration.Dynamic addServlet(String s, Class<? extends Servlet> aClass) {
return null;
}
#Override
public <T extends Servlet> T createServlet(Class<T> aClass) throws ServletException {
return null;
}
#Override
public ServletRegistration getServletRegistration(String s) {
return null;
}
#Override
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
return null;
}
#Override
public FilterRegistration.Dynamic addFilter(String s, String s1) {
return null;
}
#Override
public FilterRegistration.Dynamic addFilter(String s, Filter filter) {
return null;
}
#Override
public FilterRegistration.Dynamic addFilter(String s, Class<? extends Filter> aClass) {
return null;
}
#Override
public <T extends Filter> T createFilter(Class<T> aClass) throws ServletException {
return null;
}
#Override
public FilterRegistration getFilterRegistration(String s) {
return null;
}
#Override
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
return null;
}
#Override
public SessionCookieConfig getSessionCookieConfig() {
return null;
}
#Override
public void setSessionTrackingModes(Set<SessionTrackingMode> set) {
}
#Override
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
return null;
}
#Override
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
return null;
}
#Override
public void addListener(String s) {
}
#Override
public <T extends EventListener> void addListener(T t) {
}
#Override
public void addListener(Class<? extends EventListener> aClass) {
}
#Override
public <T extends EventListener> T createListener(Class<T> aClass) throws ServletException {
return null;
}
#Override
public JspConfigDescriptor getJspConfigDescriptor() {
return null;
}
#Override
public ClassLoader getClassLoader() {
return null;
}
#Override
public void declareRoles(String... strings) {
}
};
}
#Override
public void setMaxInactiveInterval(int interval) {
}
#Override
public int getMaxInactiveInterval() {
return 0;
}
#Override
public HttpSessionContext getSessionContext() {
return null;
}
#Override
public Object getAttribute(String name) {
return attributes.get(name);
}
#Override
public Object getValue(String name) {
return null;
}
#Override
public Enumeration<String> getAttributeNames() {
return null;
}
#Override
public String[] getValueNames() {
return new String[0];
}
#Override
public void setAttribute(String name, Object value) {
attributes.put(name,value);
}
#Override
public void putValue(String name, Object value) {
}
#Override
public void removeAttribute(String name) {
}
#Override
public void removeValue(String name) {
}
#Override
public void invalidate() {
}
#Override
public boolean isNew() {
return false;
}
}
There are ways to avoid mocking getServletContext() and RequestDispatcher with a little minor refactoring, or you can just choose to mock them.
Here are 3 possible approaches:
1) You could put the code that gets the ServletContext and forwards to the jsp page (the last 3 lines of your doPost()) in a protected method (let's call it dispatchToJSP()), and in your test you call doPost() on a subclass of StockSearchServlet which overrides dispatchToJSP() to just do an assert to verify the jsp path.
For example, in your test:
StockSearchServlet stockSearchServlet = new StockSearchServlet() {
#Override
protected void dispatchToJSP(String path) {
assertEquals("verify jsp path", path, "/stockquoteResults.jsp");
}
};
You might also want the overridden method to set a boolean flag in the subclass indicating that the method was called, in which case it may be better to use a non-anonymous subclass with a method to retrieve the flag.
2) A more elegant approach might be a refactoring to delegate the task of dispatching to the jsp to a specialized class (via an interface, preferably - let's call it IDispatcher) which does only dispatching, and the you mock that interface to verify that it was called with the correct jsp path and then create a separate test class to test your real IDispatcher implementation properly in an isolated test. So you would replace the last 3 lines of your doPost() by this.dispatcher.forwardTo("/stockquoteResults.jsp"); and in your test you would set a mock dispatcher in the servlet under test and call verify(mockDispatcher).forwardTo("/stockquoteResults.jsp"); or something like that. This is probably the approach resulting in the cleanest, best-designed, most re-usable code, but it's more work. If you have only 1 servlet, it might not be worth the extra work.
3) If you do decide to just mock everything without modifying your StockSearchServlet class itself, the trick of testing a subclass of StockSearchServlet allows you to overrride getServletContext() to return a mock (which would in turn return a mock of RequestDispatcher):
final ServletContext myMockServletContext = mock(ServletContext.class);
StockSearchServlet stockSearchServlet = new StockSearchServlet() {
#Override
public ServletContext getServletContext() {
return myMockServletContext;
}
};
This third approach is simple, but it feels ugly because it's very implementation-dependent and has mocks returning mocks. The servlet API doesn't change often, though, so I think it's okay for this situation, and the mocks have to return mocks because of questionable design in the servlet API (why isn't there just a forward() method in HttpServlet?).

how to work with WritableComparator Hadoop

Below are my code snippet for using WritableComparator, but it does not work
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
public class MovieComparator extends WritableComparator{
public MovieComparator(){
super(Movie.class);
}
#Override
public int compare(WritableComparable o,WritableComparable o2){
System.out.println("in compare");
Movie m = (Movie)o;
Movie m2 = (Movie)o2;
System.out.println(m.compareTo(m2));
return m.movieId.compareTo(m2.movieId);
}
}
public class Movie implements WritableComparable {
Text movieId;
Text movieTitle;
public Movie(Text movieId, Text movieTitle) {
this.movieId = movieId;
this.movieTitle = movieTitle;
}
public Movie(){
}
public String getMovieId() {
return movieId.toString();
}
public void setMovieId(String movieId) {
this.movieId = new Text(movieId);
}
public String getMovieTitle() {
return movieTitle.toString();
}
public void setMovieTitle(String movieTitle) {
this.movieTitle = new Text(movieTitle);
}
#Override
public void readFields(DataInput in) throws IOException {
//movieId = in.read;
movieId.readFields(in);
movieTitle.readFields(in);
}
#Override
public void write(DataOutput out) throws IOException {
//out.writeUTF(movieId);
//out.writeUTF(movieTitle);
movieId.write(out);
movieTitle.write(out);
}
#Override
public int compareTo(Movie o) {
// System.out.println("in compareTo");
int res=movieTitle.compareTo(o.movieTitle);
return res;
}
#Override
public int hashCode(){
return movieId.hashCode();
}
#Override
public boolean equals(Object o){
Movie m=(Movie)o;
return movieId.equals(m.movieId);
}
#Override
public String toString(){
return movieTitle.toString();
}
}
In driver class I am setting the comparator by below line
job.setSortComparatorClass(MovieComparator.class);
Can any body tell me where I am wrong in this at it gives exception below
14/09/08 14:17:03 WARN mapred.LocalJobRunner: job_local_0001
java.io.IOException: Spill failed
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:1029)
at org.apache.hadoop.mapred.MapTask$NewOutputCollector.write(MapTask.java:691)
at org.apache.hadoop.mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.java:80)
at com.impetus.MovieMapper.map(MovieMapper.java:44)
at com.impetus.MovieMapper.map(MovieMapper.java:1)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:764)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:370)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:212)
I found the issue that Instead of using super(Movie.class), I will have to use super(Movie.class,true). As by sending true, WritableComparator will instantiate the object other wise it will pass null in compare method

java- error when i am trying to convert xml response into pojo using xstream

I am getting an error for the following code in a java web app--
XStream xstream = new XStream();
apiresponse myClassObject;
myClassObject= xstream.fromXML(resp);
The error is shown for the line of code just above this line--
error="Type mismatch- cannot convert from Object to apiresponse"
Given below is the XML that I have to parse---
<apiresponse version="1" xmlns="http://ahrefs.com/schemas/api/links/1">
<resultset_links count="2">
<result>
<source_url>http://ahrefs.com/robot/</source_url>
<destination_url>http://blog.ahrefs.com/</destination_url>
<source_ip>50.22.24.236</source_ip>
<source_title>Ahrefs – backlinks research tool</source_title>
<visited>2011-08-31T07:56:53Z</visited>
<anchor>Blog</anchor>
<rating>257.674000</rating>
<link_type>text</link_type>
<is_nofollow>false</is_nofollow>
</result>
<result>
<source_url>http://apps.vc/</source_url>
<destination_url>http://ahrefs.com/robot/</destination_url>
<source_ip>64.20.55.86</source_ip>
<source_title>Device info</source_title>
<visited>2011-08-27T18:59:31Z</visited>
<anchor>http://ahrefs.com/robot/</anchor>
<rating>209.787100</rating>
<link_type>text</link_type>
<is_nofollow>false</is_nofollow>
</result>
</resultset_links>
</apiresponse>
I have created the following java classes to obtain data from above xml---
package com.arvindikchari.linkdatasmith.domain;
final public class apiresponse {
protected resultset_links rlinks;
public apiresponse() {
}
public resultset_links getRlinks()
{
return rlinks;
}
public setRlinks(resultset_links rlinks)
{
this.rlinks=rlinks;
}
}
final public class resultset_links {
protected List<result> indiv_result = new ArrayList<result>();
public resultset_links() {
}
public List<result> getIndiv_result()
{
return List;
}
public void setIndiv_result(List<result> indiv_result)
{
this.indiv_result=indiv_result;
}
}
final public class result {
protected String source_url;
protected String destination_url;
protected String source_ip;
protected String source_title;
protected String visited;
protected String anchor;
protected String rating;
protected String link_type;
public result() {
}
public String getSource_url()
{
return source_url;
}
public void setSource_url(String source_url)
{
this.source_url=source_url;
}
public String getDestination_url()
{
return destination_url;
}
public void setDestination_url(String destination_url)
{
this.destination_url=destination_url;
}
public String getSource_ip()
{
return source_ip;
}
public void setSource_ip(String source_ip)
{
this.source_ip=source_ip;
}
public String getSource_title()
{
return source_title;
}
public void setSource_title(String source_title)
{
this.source_title=source_title;
}
public String getVisited()
{
return visited;
}
public void setVisited(String visited)
{
this.visited=visited;
}
public String getAnchor()
{
return anchor;
}
public void setAnchor(String anchor)
{
this.anchor=anchor;
}
public String getRating()
{
return rating;
}
public void setRating(String rating)
{
this.rating=rating;
}
public String getLink_type()
{
return link_type;
}
public void setLink_type(String link_type)
{
this.link_type=link_type;
}
}
What am I doing wrong here?
You have many errors, but the one corresponding to your message is you have to cast the result of xstream.fromXML to an apiresponse' object :
apiresponse result = (apiresponse)xstream.fromXML(resp);
Moreover, the code you provided (the Java classes) do not compile, there are many errors.
Here are some improvements :
Result.java :
#XStreamAlias("result")
public class Result {
protected String source_url;
protected String destination_url;
protected String source_ip;
protected String source_title;
protected String visited;
protected String anchor;
protected String rating;
protected String link_type;
protected Boolean is_nofollow;
public Result() {
}
public String getSource_url()
{
return source_url;
}
public void setSource_url(String source_url)
{
this.source_url=source_url;
}
public String getDestination_url()
{
return destination_url;
}
public void setDestination_url(String destination_url)
{
this.destination_url=destination_url;
}
public String getSource_ip()
{
return source_ip;
}
public void setSource_ip(String source_ip)
{
this.source_ip=source_ip;
}
public String getSource_title()
{
return source_title;
}
public void setSource_title(String source_title)
{
this.source_title=source_title;
}
public String getVisited()
{
return visited;
}
public void setVisited(String visited)
{
this.visited=visited;
}
public String getAnchor()
{
return anchor;
}
public void setAnchor(String anchor)
{
this.anchor=anchor;
}
public String getRating()
{
return rating;
}
public void setRating(String rating)
{
this.rating=rating;
}
public String getLink_type()
{
return link_type;
}
public void setLink_type(String link_type)
{
this.link_type=link_type;
}
public Boolean getIs_nofollow() {
return is_nofollow;
}
public void setIs_nofollow(Boolean is_nofollow) {
this.is_nofollow = is_nofollow;
}
ResultsetLinks.java :
#XStreamAlias("resultset_links")
public class ResultsetLinks {
#XStreamImplicit(itemFieldName="result")
protected List<Result> indivResult = new ArrayList<Result>();
public ResultsetLinks() {
}
public List<Result> getResult()
{
return indivResult;
}
public void setResult(List<Result> indiv_result)
{
this.indivResult =indiv_result;
}
}
ApiResponse.java :
#XStreamAlias("apiresponse")
public class ApiResponse {
#XStreamAlias("resultset_links")
protected ResultsetLinks rlinks;
public ApiResponse() {
}
public ResultsetLinks getRlinks()
{
return rlinks;
}
public void setRlinks(ResultsetLinks rlinks)
{
this.rlinks=rlinks;
}
}
And finally your code to unmarshall the XML :
XStream xstream = new XStream();
xstream.processAnnotations(ApiResponse.class);
xstream.processAnnotations(ResultsetLinks.class);
xstream.processAnnotations(Result.class);
ApiResponse result = (ApiResponse)xstream.fromXML(resp);
All this code is working fine with Xstream 1.4.2
Try to follow Sun's coding convention for your classes name, attributes names, etc...
Use XstreamAliases to adapt the Java class name to the XML name.

Categories

Resources