I've hit a wall using Objectify for the google appengine datastore when filtering on boolean values. This is roughly what I've:
class Task implements Serializable {
...
boolean failed;
...
}
No matter what i do when i search, i always get an empty response although there are objects in the db that has failed = false
Examples:
ofy().query(Task.class).filter("failed",false).list()
ofy().query(Task.class).filter("failed",Boolean.FALSE).list()
ofy().query(Task.class).filter("failed",0).list()
ofy().query(Task.class).filter("failed","false").list()
ofy().query(Task.class).filter("failed","FALSE").list()
I found this old question while Googling and I wanted to clear it up.
You should be able to query by boolean fields as long as they are indexed at the time that they entered the datastore. Here's a complete unit test using Objectify and the App Engine unit test library (To run it, you have to link in the unit test jar described here). The following test passes. So the problem lies elsewhere, and I suggest that you use unit tests to discover it.
import static org.junit.Assert.*;
import javax.persistence.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.appengine.api.datastore.QueryResultIterator;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
class FakeEntity {
#Id public Long id;
public boolean boolProp;
public boolean equals(Object other) {
return other != null &&
other instanceof FakeEntity &&
((FakeEntity)other).id == this.id &&
((FakeEntity)other).boolProp == this.boolProp;
}
}
public class FakeEntityTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
#Test
public void testBoolQuery() {
ObjectifyFactory objectifyFactory = ObjectifyService.factory();
objectifyFactory.register(FakeEntity.class);
Objectify objectify = objectifyFactory.begin();
FakeEntity entityFalse = new FakeEntity();
FakeEntity entityTrue = new FakeEntity();
entityTrue.boolProp = true;
objectifyFactory.begin().put(entityFalse);
objectifyFactory.begin().put(entityTrue);
assertArrayEquals(
new FakeEntity[] {entityFalse},
objectify.query(FakeEntity.class)
.filter("boolProp", false).list().toArray());
assertArrayEquals(
new FakeEntity[] {entityTrue},
objectify.query(FakeEntity.class)
.filter("boolProp", true).list().toArray());
assertArrayEquals(
new FakeEntity[] {entityTrue},
objectify.query(FakeEntity.class)
.filter("boolProp", true).list().toArray());
assertArrayEquals(
new FakeEntity[] {entityTrue},
objectify.query(FakeEntity.class)
.filter("boolProp", Boolean.TRUE).list().toArray());
// Filtering on integers and strings WON'T work:
assertArrayEquals(
new FakeEntity[] {},
objectify.query(FakeEntity.class)
.filter("boolProp", "true").list().toArray());
assertArrayEquals(
new FakeEntity[] {},
objectify.query(FakeEntity.class)
.filter("boolProp", 0).list().toArray());
}
}
You haven't Indexed boolean failed property.
If a field is not indexed, filter will not work in objectify datastore.
So to make it work, add
#Index boolean failed;
Now your filter will work.
Please note that though indexed, already saved values cannot be filtered. So either create new records and save or read all datastore entities and save it again.
Hope this helps.
Related
I am trying to mock a very simple line of code that is used to query the DynamoDB using Java. Here is some sample code for the query -
List<Pojo> result;
try {
if (filters == null) {
this.queryExpression = new DynamoDBQueryExpression<Pojo>()
.withKeyConditionExpression(partitionKeyCondition)
.withExpressionAttributeValues(this.eav);
} else {
setFilterQueryExpression(filters);
}
result = this.dynamoDBMapper.query(Pojo.class, queryExpression);
} catch (final Exception e) {
throw new InternalServerException("Something went wrong with the database query: ", e);
}
The above piece of code works and I am able to retrieve a List of rows that automatically get deserialized into the Pojo.
I am now trying to Mock the this.dynamoDBMapper.query call as follows -
#Mock
private DynamoDBMapper mapper;
List<Pojo> result = new ArrayList<>();
when(mapper.query(Pojo.class,Mockito.any(DynamoDBQueryExpression.class)).thenReturn(result);
I am unable to do that with error -
Cannot resolve method 'thenReturn(java.util.List<com.amazon.xxx.xxx.Pojo>)'
I also tried another way -
doReturn(result).when(mapper).query(Pojo.class, Mockito.any(DynamoDBQueryExpression.class));
That seems to compile but the test fails with error -
org.mockito.exceptions.misusing.WrongTypeOfReturnValue
I have looked at other sample where the expected output of the query is of type PaginatedQueryList , I have tried changing to that as well. But I am still not sure why the above throws an error.
Do you also get the error when you use ArgumentMatchers?
Mockito.when(mapper.query(ArgumentMatchers.any(Pojo.class),ArgumentMatchers.any(DynamoDBQueryExpression.class)).thenReturn(result));
Do you also get the error if you expand the ArgumentMatchers (temporarily)?
Mockito.when(mapper.query(ArgumentMatchers.any(),ArgumentMatchers.any()).thenReturn(result));
As it turns out, you are missing a parenthesis before .thenReturn in order to complete the when part. Once you add it and switch from return type List to PaginatedQueryList, it should compile. Also note that any is a matcher. Once you specifiy a matcher, all arguments need to be matchers, therefore use eq etc. for your Pojo type. Otherwise, Mockito will show a InvalidUseOfMatchersException during runtime. Here is a simplified example that works for me:
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class MockTest {
#Test
void test() {
DynamoDBMapper mapperMock = mock(DynamoDBMapper.class);
PaginatedQueryList<String> expected = mock(PaginatedQueryList.class);
// Note that when needs to be completed before thenReturn can be called.
when(mapperMock.query(eq(String.class), Mockito.any(DynamoDBQueryExpression.class))).thenReturn(expected);
QueryService queryService = new QueryService(mapperMock);
PaginatedQueryList<String> actual = queryService.query();
assertEquals(expected, actual);
}
public class QueryService {
private final DynamoDBMapper mapper;
public QueryService(DynamoDBMapper mapper) {
this.mapper = mapper;
}
public PaginatedQueryList<String> query() {
DynamoDBQueryExpression<String> queryExpression = new DynamoDBQueryExpression<>();
return mapper.query(String.class, queryExpression);
}
}
}
I have a class:
public class RequestHandler implements HttpHandler {
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(() -> serverContext.getRequestReceiver()
.receiveFullBytes((httpServerExchange, reqBytes) -> {
// business logic along with few function call
}
)
);
}
}
I want to write a unit test case to test my business logic. I am not sure how to do it with 2 levels of a lambda expression insider a dispatcher? Can someone please suggest a good way to write test cases?
I know that we can move business logic to new class and can test it (i guess it's better designed) but curious to know what if it's part of some legacy code or something that we can't change, how can we test it?
Under the assumption that somewhere in your buisness logic you forward the received message (or whatever you do with it) to somewhere else, you can just test your code as usual.
Note that HttpServerExchange is a final class, so you need to use a Mockito version that supports final mocking - and you have to enable it, as described here.
To get around the lambda expression you need to use thenAnswer or doAnswer to trigger the invocation of the correct interface method manually.
A simple example could look like this:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.Answer;
import io.undertow.io.Receiver;
import io.undertow.io.Receiver.FullBytesCallback;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
#ExtendWith(MockitoExtension.class)
public class RequestHandlerTest {
static class BuisnessLogic {
public void someMethod(HttpServerExchange httpServerExchange, byte[] reqBytes) {
}
}
static class RequestHandler implements HttpHandler {
BuisnessLogic logic;
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(
() -> serverContext.getRequestReceiver().receiveFullBytes(
(httpServerExchange, reqBytes) -> {
logic.someMethod(httpServerExchange, reqBytes);
}
)
);
}
}
#Mock
BuisnessLogic logic;
#InjectMocks
RequestHandler handler;
#Test
public void test() throws Exception {
byte[] message = new byte[] {1,2,3};
HttpServerExchange serverContext = Mockito.mock(HttpServerExchange.class);
// 1st lambda
Mockito.when(serverContext.dispatch(Mockito.any(Runnable.class)))
.thenAnswer((Answer<HttpServerExchange>) invocation -> {
Runnable runnable = invocation.getArgument(0);
runnable.run();
return serverContext;
});
// 2nd lambda
Receiver receiver = Mockito.mock(Receiver.class);
Mockito.doAnswer((Answer<Void>) invocation -> {
FullBytesCallback callback = invocation.getArgument(0);
callback.handle(serverContext, message);
return null;
}).when(receiver).receiveFullBytes(Mockito.any(FullBytesCallback.class));
Mockito.when(serverContext.getRequestReceiver()).thenReturn(receiver);
// class under test - method invocation
handler.handleRequest(serverContext);
// buisness logic call verification
ArgumentCaptor<HttpServerExchange> captor1 = ArgumentCaptor.forClass(HttpServerExchange.class);
ArgumentCaptor<byte[]> captor2 = ArgumentCaptor.forClass(byte[].class);
Mockito.verify(logic).someMethod(captor1.capture(), captor2.capture());
Assertions.assertEquals(serverContext, captor1.getValue());
Assertions.assertEquals(message, captor2.getValue());
}
}
As others already mentioned you should only use that approach for legacy code.
A simple refactoring could just push the entire part you need to test into its own method, which - in the example above - would just be the buisness logic itself.
There is no explicit need to test the undertow framework yourself.
I am digging on Jackson 2 and I want to know where and how the getter-method name gets converted into a property name.
I have tried:
PropertyName foo = new PropertyName("getKarli");
System.out.println(foo.getSimpleName());
I and I have found BeanProperty.Std() but this one have a lot of wired constructors. The api is bigger then expected :-) Is there a Jackson class and method where I can just pass the method and get back the correct property text used in the json?
EDIT:
I have also tried this one but that gives me a NullPointer
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyName;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class Test {
public String getKarli() {
return null;
}
public static void main(String[] a) throws Exception {
node.remove("geheim");
System.out.println(node.toString());
Annotated aa = new AnnotatedMethod(Test.class.getMethod("getKarli"), null, null);
System.out.println(
new ObjectMapper().getSerializationConfig().getAnnotationIntrospector().findNameForSerialization(aa)
);
// new BeanProperty.Std()
}
}
Found it.
String name = BeanUtil.okNameForRegularGetter(p, p.getName(), true);
if(name == null) name = BeanUtil.okNameForIsGetter(p, p.getName(), true);
I create custom Elasticsearch plugin. Now I want to write a test for this plugin.
My expectations were - that I could run embedded Elasticsearch instance, set up it properly and then do some testing (index some documents, then query for it)
Problem is that I couldn't set up my plugin properly
Custom plugin code is parsing JSON query and set up some objects for later usage:
public class CustomQueryParserPlugin extends AbstractPlugin {
public static final String PLUGIN_NAME = "custom_query";
private final Settings settings;
#Inject
public CustomQueryParserPlugin (Settings settings) {
this.settings = settings;
}
#Override
public String name() {
return PLUGIN_NAME;
}
#Override
public String description() {
return "custom plugin";
}
public void onModule(IndicesQueriesModule module) {
module.addQuery(new CustomQueryParser(settings));
}
}
Test code:
public class CustomParserPluginTest extends ElasticsearchSingleNodeTest {
private static Node newNode() {
final Settings settings = ImmutableSettings.builder()
.put(ClusterName.SETTING, nodeName())
.put("node.name", nodeName())
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
.put(EsExecutors.PROCESSORS, 1) // limit the number of threads created
.put("http.enabled", false)
.put("plugin.types", CustomParserPlugin.class.getName())
.put("path.plugins", pathToPlugin)
.put("index.store.type", "ram")
.put("config.ignore_system_properties", true) // make sure we get what we set :)
.put("gateway.type", "none").build();
Node build = NodeBuilder.nodeBuilder().local(true).data(true).settings(
settings).build();
build.start();
assertThat(DiscoveryNode.localNode(build.settings()), is(true));
return build;
}
#Test
public void jsonParsing() throws URISyntaxException {
final Client client = newNode().client();
final SearchResponse test = client.prepareSearch("test-index").setSource(addQuery()).execute().actionGet();
}
private String addQuery() {
return "{"match_all":{"boost":1.2}}"
}
I've try multiple values for pathToPlugin - but nothing seems to works well, because JSON query always give me an exception:
QueryParsingException[[test-index] No query registered for [custom_query]];
All documentation I could find was about installing plugins and testing them on some local Elasticsearch installation.
What I am doing wrong here? Is there any documentation or examples of tests like that?
UPD. Here is a repo with extracted code of CustomQueryParserPlugin - https://github.com/MysterionRise/es-custom-parser
May be in initialize section in test I need to create in memory index?
To write tests for you plugin you can use Elasticsearch Cluster Runner.
For reference check how MinHash Plugin wrote test.
UPDATE:
I've changed CustomParserPluginTest class to use Elasticsearch Cluster Runner:
import static org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.newConfigs;
import java.util.Map;
import junit.framework.TestCase;
import org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.ImmutableSettings.Builder;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.get.GetField;
import org.junit.Assert;
import org.elasticsearch.action.search.SearchResponse;
import static org.hamcrest.core.Is.is;
public class CustomParserPluginTest extends TestCase {
private ElasticsearchClusterRunner runner;
#Override
protected void setUp() throws Exception {
// create runner instance
runner = new ElasticsearchClusterRunner();
// create ES nodes
runner.onBuild(new ElasticsearchClusterRunner.Builder() {
#Override
public void build(final int number, final Builder settingsBuilder) {
}
}).build(newConfigs().ramIndexStore().numOfNode(1));
// wait for yellow status
runner.ensureYellow();
}
#Override
protected void tearDown() throws Exception {
// close runner
runner.close();
// delete all files
runner.clean();
}
public void test_jsonParsing() throws Exception {
final String index = "test_index";
runner.createIndex(index, ImmutableSettings.builder().build());
runner.ensureYellow(index);
final SearchResponse test = runner.client().prepareSearch(index).setSource(addQuery()).execute().actionGet();
}
private String addQuery() {
return "{\"match_all\":{\"boost\":1.2}}";
}
}
I've created es-plugin.properties(pluginrootdirectory\src\main\resources) file with following content which will force elasticsearch instance to load plugin:
plugin=CustomQueryParserPlugin
When you will run the this test you will see in the output that the newly created insance of elasticsearch loaded the plugin.
[2015-04-29 19:22:10,783][INFO ][org.elasticsearch.node ] [Node 1]
version[1.5 .0], pid[34360], build[5448160/2015-03-23T14:30:58Z]
[2015-04-29 19:22:10,784][INFO ][org.elasticsearch.node ] [Node 1]
initializin g ... [2015-04-29 19:22:10,795][INFO
][org.elasticsearch.plugins] [Node 1] loaded [custom_query], sites []
[2015-04-29 19:22:13,342][INFO ][org.elasticsearch.node ] [Node 1]
initialized
[2015-04-29 19:22:13,342][INFO ][org.elasticsearch.node ] [Node 1]
starting .. .
Hope this helps.
public static UserDetail UserDetail.findUserDetail(Long id) {
if (id == null) return null;
return entityManager().find(UserDetail.class, id);
}
We are using spring Roo. Above is Roo generated finder method. Partial stack trace is as follows:
Caused by: org.hibernate.WrongClassException: Object with id: 1501237 was not of the specified subclass: com.***.***.user.UserDetail (Discriminator: FacebookUserDetail)
Has anyone come across this exception?
EDIT
This question and following questions are related to same issue.
Java class file truncated
I have two projects. My one project (say project2) depends on another project(project2). Both projects are maven project and project1 is listed in dependancies of project2. When I compile project2, all the class files from project1 should be copied to project2 (I imagine). But, I see that the file size of one of the class files in project1 is different than file size of class file for the same class in project2. If I decompile the files I get following results.
Decompiled FacebookUserDetail.class from project1:
package com.***.domain.user.external;
import com.***.domain.user.UserDetailType;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.TypedQuery;
import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.internal.CFlowCounter;
import org.aspectj.runtime.reflect.Factory;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect;
import org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
#Configurable
#Entity
public class FacebookUserDetail extends ExternalUserDetail
{
public FacebookUserDetail()
{
JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_1, this, this); if ((!AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)getClass().getAnnotation(Configurable.class))) && (AbstractDependencyInjectionAspect.ajc$if$6f1(localJoinPoint))) AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
}
public static FacebookUserDetail findFacebookUserDetailByFacebookId(String facebookId)
{
String str = facebookId; JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, null, null, str); if ((AnnotationDrivenStaticEntityMockingControl.ajc$cflowCounter$1.isValid()) && (AnnotationDrivenStaticEntityMockingControl.hasAspect())) return (FacebookUserDetail)findFacebookUserDetailByFacebookId_aroundBody1$advice(str, localJoinPoint, AnnotationDrivenStaticEntityMockingControl.aspectOf(), null, ajc$tjp_0, localJoinPoint); return findFacebookUserDetailByFacebookId_aroundBody0(str, localJoinPoint);
}
public UserDetailType getExternalUserDetailType()
{
return UserDetailType.FACEBOOK;
}
static
{
ajc$preClinit(); }
public static long countFacebookUserDetails() { return FacebookUserDetail_Roo_Entity.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_Entity$com_nim_domain_user_external_FacebookUserDetail$countFacebookUserDetails(); }
public static List<FacebookUserDetail> findAllFacebookUserDetails() { return FacebookUserDetail_Roo_Entity.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_Entity$com_nim_domain_user_external_FacebookUserDetail$findAllFacebookUserDetails(); }
public static FacebookUserDetail findFacebookUserDetail(Long paramLong) { return FacebookUserDetail_Roo_Entity.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_Entity$com_nim_domain_user_external_FacebookUserDetail$findFacebookUserDetail(paramLong); }
public static List<FacebookUserDetail> findFacebookUserDetailEntries(int paramInt1, int paramInt2) { return FacebookUserDetail_Roo_Entity.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_Entity$com_nim_domain_user_external_FacebookUserDetail$findFacebookUserDetailEntries(paramInt1, paramInt2); }
public static TypedQuery<FacebookUserDetail> findFacebookUserDetailsByUserIdEquals(String paramString) { return FacebookUserDetail_Roo_Finder.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_Finder$com_nim_domain_user_external_FacebookUserDetail$findFacebookUserDetailsByUserIdEquals(paramString); }
public String toString() { return FacebookUserDetail_Roo_ToString.ajc$interMethod$com_nim_domain_user_external_FacebookUserDetail_Roo_ToString$com_nim_domain_user_external_FacebookUserDetail$toString(this); }
}
Decompiled FacebookUserDetail.class from project2
package com.***.domain.user.external;
import com.***.domain.user.UserDetailType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.runtime.internal.CFlowCounter;
import org.aspectj.runtime.reflect.Factory;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect;
import org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect;
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
public class FacebookUserDetail extends ExternalUserDetail
{
public FacebookUserDetail()
{
JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_1, this, this); if ((!AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)getClass().getAnnotation(Configurable.class))) && (AbstractDependencyInjectionAspect.ajc$if$6f1(localJoinPoint))) AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
}
public static FacebookUserDetail findFacebookUserDetailByFacebookId(String facebookId)
{
String str = facebookId; JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, null, null, str); if ((AnnotationDrivenStaticEntityMockingControl.ajc$cflowCounter$1.isValid()) && (AnnotationDrivenStaticEntityMockingControl.hasAspect())) return (FacebookUserDetail)findFacebookUserDetailByFacebookId_aroundBody1$advice(str, localJoinPoint, AnnotationDrivenStaticEntityMockingControl.aspectOf(), null, ajc$tjp_0, localJoinPoint); return findFacebookUserDetailByFacebookId_aroundBody0(str, localJoinPoint);
}
public UserDetailType getExternalUserDetailType()
{
return UserDetailType.FACEBOOK;
}
static
{
ajc$preClinit();
}
}
My question is: What are possible reasons for truncated class file in project2?
As far as I understand from the error you have the following scenario:
you request an entity of type UserDetail with that ID (which should have the DTYPE/discriminator column value equal to FacebookUserDetail or other that extend UserDetail), but in your DB the DTYPE is another. You have to correct your DB for that.
Or it could also be, that FacebookUserDetail is not recognized as being a DTYPE of the same hierarchy. Try debugging a bit, e.g testing what is returned if you search for a FacebookUserDetail instance of the same ID.
It looks like your super class and subclasse didn't share the same id in the database for the requested record 1501237
It is obvious you have an inheritance problem, take a look at http://en.wikibooks.org/wiki/Java_Persistence/Inheritance