Restlet getRequest is always null on a Resource - rest

I have the following
public synchronized Restlet createRoot() {
Router router = new Router(getContext());
router.attach("/search/{query}", SearchResource.class);
return router;
}
So query is the search query (variable)
I am trying to get this variable from my resource but I am always returned null.
public SearchResource() {
searchQuery = (String) getRequestAttributes().get("query");
}
I am getting a null pointer at getRequestAttributes() or if I try getRequest().getAttributes()
Am I doing something wrong?

This works for me :
public class SearchResource extends ServerResource {
#Get
public YourBean getYourBean() {
String searchQuery = (String) getRequest().getAttributes().get("searchQuery");
.....
}
}

Related

Mutiny reactive - persist to DB if upstream is not null

I working on a Quarkus + MongoDB Reactive+ Mutiny application. I have a Person object and Event Object. I am creating a new event for a person. My uri looks like this
POST /person/{personId}/event
I need to first check if the person exists in MongoDB. If the person exists then save event. If person does not exist then create a Error Status and return. I am tried everything but I am stuck and getting error that required return type is Uni but required type is Uni. I tried with transformToUni as well but it did not work. Also tried few other ways like onItemOrFailure() etc. but nothing seems to work.
Here's the full Code.
public class EventResource {
#Inject
EventRepository eventRepository;
#Inject
PersonRepository personRepository;
#POST
#Path("/{person_id}/event")
public Uni<Response> create(Event event, #PathParam("person_id") String personId){
//Check if personId exist.
Uni<Person> uniPerson = personRepository.getPersonById(personId);
//THIS WORKS BUT ON FAILURE IS TREATED WHEN ERROR IS RAISED FOR EeventRepository.craete() and not if person is not found.
/*return uniPerson.onItem().ifNotNull()
.transformToUni(pid -> eventRepository.create(event, pid.getId()))
.onItem().transform(e -> Response.ok().entity(e).build())
.onFailure()
.recoverWithItem(f-> {
AStatus status = createErrorStatus(f.getMessage());
return Response.serverError().entity(status).build();
});
*/
Uni<Response> eventResp = uniPerson.onItem().transform(person -> {
if(person==null)
return Response.serverError().build();
else{
return eventRepository.create(event, person.getId())
.onItem().transform(event1 -> Response.ok(event1).build());
}
});
return eventResp;
}
You can use mutiny ifNull:
#POST
#Path("/{person_id}/event")
public Uni<Response> create(Event event, #PathParam("person_id") String personId){
return personRepository
.getPersonById(personId)
.onItem().ifNotNull().transformToUni(person -> createEvent(event, person))
.onItem().ifNull().continueWith(this::personNotFound)
// This onFailure will catch all the errors
.onFailure()
.recoverWithItem(f-> {
AStatus status = createErrorStatus(f.getMessage());
return Response.serverError().entity(status).build();
});
}
private Uni<Response> createEvent(Event event, Person person) {
return eventRepository
.create(event, person.getId())
.map( e -> Response.ok().entity(e).status(CREATED).build())
}
private Response personNotFound() {
return Response.serverError().build();
}
The error you are seeing is because when the item is not null, you are returning a Uni<Uni<Response>>. This is one way to fix it:
Uni<Response> eventResp = uniPerson
.chain(person -> {
if (person==null)
return Uni.createFrom().item(Response.serverError().build());
else {
return eventRepository
.create(event, person.getId())
.map(event1 -> Response.ok(event1).build());
}
});
I'm using map and chain because they are shorter, but you can replace them with onItem().transform(...) and onItem().transformToUni(...).

How can I ignore a "$" in a DocumentContent to save in MongoDB?

My Problem is, that if I save a Document with a $ inside the content, Mongodb gives me an exception:
java.lang.IllegalArgumentException: Invalid BSON field name $ xxx
I would like that mongodb ignores the $ character in the content.
My Application is written in java. I read the content of the File and put it as a string into an object. After that the object will be saved with a MongoRepository class.
Someone has any ideas??
Example content
Edit: I heard mongodb has the same problem wit dot. Our Springboot found i workaround with dot, but not for dollar.
How to configure mongo converter in spring to encode all dots in the keys of map being saved in mongo db
If you are using Spring Boot you can extend MappingMongoConverter class and add override methods that do the escaping/unescaping.
#Component
public class MappingMongoConverterCustom extends MappingMongoConverter {
protected #Nullable
String mapKeyDollarReplacemant = "characters_to_replace_dollar";
protected #Nullable
String mapKeyDotReplacement = "characters_to_replace_dot";
public MappingMongoConverterCustom(DbRefResolver dbRefResolver, MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
super(dbRefResolver, mappingContext);
}
#Override
protected String potentiallyEscapeMapKey(String source) {
if (!source.contains(".") && !source.contains("$")) {
return source;
}
if (mapKeyDotReplacement == null && mapKeyDollarReplacemant == null) {
throw new MappingException(String.format(
"Map key %s contains dots or dollars but no replacement was configured! Make "
+ "sure map keys don't contain dots or dollars in the first place or configure an appropriate replacement!",
source));
}
String result = source;
if(result.contains(".")) {
result = result.replaceAll("\\.", mapKeyDotReplacement);
}
if(result.contains("$")) {
result = result.replaceAll("\\$", mapKeyDollarReplacemant);
}
//add any other replacements you need
return result;
}
#Override
protected String potentiallyUnescapeMapKey(String source) {
String result = source;
if(mapKeyDotReplacement != null) {
result = result.replaceAll(mapKeyDotReplacement, "\\.");
}
if(mapKeyDollarReplacemant != null) {
result = result.replaceAll(mapKeyDollarReplacemant, "\\$");
}
//add any other replacements you need
return result;
}
}
If you go with this approach make sure you override the default converter from AbstractMongoConfiguration like below:
#Configuration
public class MongoConfig extends AbstractMongoConfiguration{
#Bean
public DbRefResolver getDbRefResolver() {
return new DefaultDbRefResolver(mongoDbFactory());
}
#Bean
#Override
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverterCustom converter = new MappingMongoConverterCustom(getDbRefResolver(), mongoMappingContext());
converter.setCustomConversions(customConversions());
return converter;
}
.... whatever you might need extra ...
}

Error : Cannot find Facebook SDK Version

the SDK 7.x is not working on Unity 5.1.0f3 , i always got the error version not found .
does someone have see this error ?
Actually, it's just a warning. But you can fix it.
There are several places where facebook plugin calls
FBBuildVersionAttribute.GetVersionAttributeOfType(typeof(AbstractFacebook));
So first, you need to modify FBBuildVersionAttribute to this:
// we are going to apply this attribute to Class
// instead of Assembly
// also make it inheritable for all implementations
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class FBBuildVersionAttribute : Attribute
{
private DateTime buildDate;
private string buildHash;
private string buildVersion;
private string sdkVersion;
public DateTime Date { get { return buildDate; } }
public string Hash { get { return buildHash; } }
public string SdkVersion { get { return sdkVersion; } }
public string BuildVersion { get { return buildVersion; } }
public FBBuildVersionAttribute(string sdkVersion, string buildVersion)
{
this.buildVersion = buildVersion;
var parts = buildVersion.Split('.');
buildDate = DateTime.ParseExact(parts[0], "yyMMdd", System.Globalization.CultureInfo.InvariantCulture);
buildHash = parts[1];
this.sdkVersion = sdkVersion;
}
public override string ToString()
{
return buildVersion;
}
public static FBBuildVersionAttribute GetVersionAttributeOfType(Type type)
{
foreach (FBBuildVersionAttribute attribute in getAttributes(type))
{
return attribute;
}
return null;
}
private static FBBuildVersionAttribute[] getAttributes(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// we want to get attributes from type instead of assmebly
return (FBBuildVersionAttribute[])(type.GetCustomAttributes(typeof(FBBuildVersionAttribute), false));
}
}
No you just need to add this attribute to AbstractFacebook:
[FBBuildVersionAttribute("7.0.1", "150604.98558e55096475c")]
public abstract class AbstractFacebook : MonoBehaviour
{
// ...
}
Note that 98558e55096475c part is trash string. It's not actual build hash, cause I don't have one.
Get the latest version of the FB Unity SDK. Change log says it's fixed now.
https://developers.facebook.com/docs/unity/change-log

Get and Set attribute values of a class using aspectJ

I am using aspectj to add some field to a existing class and annotate it also.
I am using load time weaving .
Example :- I have a Class customer in which i am adding 3 string attributes. But my issues is that I have to set some values and get it also before my business call.
I am trying the below approach.
In my aj file i have added the below, my problem is in the Around pointcut , how do i get the attribute and set the attribute.
public String net.customers.PersonCustomer.getOfflineRiskCategory() {
return OfflineRiskCategory;
}
public void net.customers.PersonCustomer.setOfflineRiskCategory(String offlineRiskCategory) {
OfflineRiskCategory = offlineRiskCategory;
}
public String net.customers.PersonCustomer.getOnlineRiskCategory() {
return OnlineRiskCategory;
}
public void net.customers.PersonCustomer.setOnlineRiskCategory(String onlineRiskCategory) {
OnlineRiskCategory = onlineRiskCategory;
}
public String net.customers.PersonCustomer.getPersonCommercialStatus() {
return PersonCommercialStatus;
}
public void net.customers.PersonCustomer.setPersonCommercialStatus(String personCommercialStatus) {
PersonCommercialStatus = personCommercialStatus;
}
#Around("execution(* net.xxx.xxx.xxx.DataMigration.populateMap(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
Object arguments[] = joinPoint.getArgs();
if (arguments != null) {
HashMap<String, String> hMap = (HashMap) arguments[0];
PersonCustomer cus = (PersonCustomer) arguments[1];
return joinPoint.proceed();
}
If anyone has ideas please let me know.
regards,
FT
First suggestion, I would avoid mixing code-style aspectj with annotation-style. Ie- instead of #Around, use around.
Second, instead of getting the arguments from the joinPoint, you should bind them in the pointcut:
Object around(Map map, PersonCustomer cust) :
execution(* net.xxx.xxx.xxx.DataMigration.populateMap(Map, PersonCustomer) && args(map, cust) {
...
return proceed(map, cust);
}
Now, to answer your question: you also need to use intertype declarations to add new fields to your class, so do something like this:
private String net.customers.PersonCustomer.OfflineRiskCategory;
private String net.customers.PersonCustomer.OnlineRiskCategory;
private String net.customers.PersonCustomer.PersonCommercialStatus;
Note that the private keyword here means private to the aspect, not to the class that you declare it on.

JERSEY - Accessing Generic List in Response

Im facing isssue in getting Jersey Generic List in client response. I need to get it as Entity for some reason.
#XmlRootElement(name="list")
#XmlSeeAlso({RESTDomain.class})
public class JAXBContainer<T> {
private List<T> items = new ArrayList<T>();
public JAXBContainer() { }
public JAXBContainer(List<T> items) {
this.items = items;
}
#XmlElementWrapper(name="items")
#XmlAnyElement(lax=true)
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
#XmlAttribute
public int getItemsSize() {
return this.items.size();
}
above is my Generic List to the resopnse
#GET
#Produces({MediaType.APPLICATION_XML})
public Response getREST(){
RESTDomain domain = new RESTDomain();
domain.setName("Adams");
domain.setPlace("Zurich");
List<RESTDomain> restDomains = new ArrayList<RESTDomain>();
restDomains.add(domain);
JAXBContainer<RESTDomain> jAXBContainer= new JAXBContainer<RESTDomain>(restDomains);
GenericEntity<JAXBContainer<RESTDomain>> genericEntity = new GenericEntity<JAXBContainer<RESTDomain>>(jAXBContainer){};
return Response.ok(genericEntity).build();
}
Im returning the container with genericEntity. I know with just List inside genericEntity i can get my Entity at my client but the problem is i need to Use my JAXBContainer for some reason.
#Test
public void restGet() throws JAXBException{
ClientConfig cc = new DefaultClientConfig();
client = Client.create(cc);
String baseURI ="http://localhost:3555/SampleREST/rest/sample";
WebResource webResource = client.resource(baseURI);
JAXBContainer<RESTDomain> jAXBContainer= webResource.get(new GenericType<JAXBContainer<RESTDomain>>(){});
System.out.println("response:: "+jAXBContainer.getItemsSize());
}
My problem is im getting the response as JAXBContainer with GenericType as desired but the size of container is 0. What am i missing here? do i have to Use any marshalling and unmarshalling Mechanisms.
But When i request this URI in browser i get the well formed XML, But it fails in client or do we have any other ways to extract entity in client. Thanks in advance
I don't see that you're setting the accept content type anywhere on the client.
Try with: webResource.accept("application/xml")