Persistence with EJB3 doesn't work - database

I have a method to save a new object in an EJB bean. This method is called, without error, but nothing changes in the database. I can't understand why.
Here is the code:
#Stateless(name = "Ar", mappedName = "ManagementBean")
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote {
...
#Override
public int storeRawSms(String raw, String requestUid, String text, String service, boolean correctlyAnalysed, Date receivedTimestamp,
boolean toBeAnalysed, String phoneNumber) {
// Get phone number, create if it dosn't exist
PhoneNumber pn = getOrCreatePhoneNumberPrivate(phoneNumber);
// Create rawSMS
RawSms rawSms = new RawSms(raw, requestUid, text, service, correctlyAnalysed, receivedTimestamp, toBeAnalysed, pn);
// Store and return result
em.persist(rawSms);
int result = rawSms.getId();
em.flush();
em.clear();
return result;
}
...
And the caller:
#PersistenceContext private EntityManager em;
...
int rawSmsIs = bean.storeRawSms(raw, requestUid, message, service, false, new Date(), true, sender);
Do you have an idea?

I see that you inject a reference to the EntityManager in the client (not sure why), but I don't see it in the session bean (maybe simply because you did not include the line in your message). Is it possible that you forgot to use the annotation #PersistenceContext in your stateless session bean?
Also, be careful: depending on the JPA implementation you are using and the generation strategy for the ids, you should call flush() before calling getId(). Indeed, if you let the DB generate your IDs, then you need a flush() to have this happen before the method returns the value.

Thanks, the prposed solution worked!
I use the container-managed transactions like this:
#Stateless(name = "Ar", mappedName = "ManagementBean")
#TransactionManagement(TransactionManagementType.CONTAINER)
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote {
....
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int storeRawSms(String raw, String requestUid, String text, String service, boolean correctlyAnalysed, Date receivedTimestamp, boolean toBeAnalysed, String phoneNumber) {
....
Thanks again!

It seems that your transaction never commited, so try changing transaction management:
#Stateless(name = "Ar", mappedName = "ManagementBean")
#TransactionManagement(TransactionManagementType.BEAN)
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote {
#Resource
private UserTransaction utx;
#Override
public int storeRawSms(..) {
try {
utx.begin();
..
em.persist(rawSms);
int result = rawSms.getId();
utx.commit();
}
catch(Exception ex) {
//EXCEPTION HANDLING
utx.rollback();
}
}
}

Related

Skip message in Kafka deserialization schema if any problems occur

I have a simple Apache Flink job that ends with a Kafka sink. I'm using a KafkaRecordSerializationSchema<CustomType> to handle the message from the previous (RichFlatMap) operator:
public final class CustomTypeSerializationSchema implements KafkaRecordSerializationSchema<CustomType> {
private static final long serialVersionUID = 5743933755381724692L;
private final String topic;
public CustomTypeSerializationSchema(final String topic) {
this.topic = topic;
}
#Override
public ProducerRecord<byte[], byte[]> serialize(final CustomType input, final KafkaSinkContext context,
final Long timestamp) {
final var result = new CustomMessage(input);
try {
return new ProducerRecord<>(topic,
JacksonJsonMapper.writeValueAsString(result).getBytes(StandardCharsets.UTF_8));
} catch (final Exception e) {
logger.warn("Unable to serialize message [{}]. This was the reason:", result, e);
}
return new ProducerRecord<>(topic, new byte[0]);
}
}
The problem I'm trying to avoid is to send an "empty" ProducerRecord — like the one that will be executed by default if something happens within the try-catch. Basically, I'm looking for a behavior similar to KafkaRecordDeserializationSchema, where what's put in the collector is what's going to be received in subsequent operators, and the rest is discarded.
Is there a way to achieve this with another *SerializationSchema type?

How take always first parameter when requested array type param in spring mvc using #RequestParam

I wrote this code.
#GetMapping("/test")
public Response search(#RequestParam String value) {
System.out.println(value);
return new Response(value)
}
Some body request like
/test?value=a&value=b&value=c
value binded a,b,c
I want always bind first parmeter. Take a, ignore b, c.
Is there way using #RequestParam?
Or have to use HttpServletRequest and parsing parameter?
In this case you can use #RequestParam List<String> value instead of #RequestParam String value, and get the first value value.get(0) ignore the rest of them
For Example
http://rentacar.com/api/v1/search?make=audi&model=A8&type=6&type=11&type=12&color=RED&color=GREY
Method
public List<Vehicle> search(
#RequestParam(value="make", required=false) String make,
#RequestParam(value="model", required=false) String model,
#RequestParam(value="type", required=false) List<String> types,
#RequestParam(value="color", required=false) List<String> colors)
{
....
}
Great question!
I wrote this code to find out how this works. I included it in the test packages.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public class ControllerTest {
#LocalServerPort
private int port;
private URL url;
#Autowired
private TestRestTemplate template;
#Before
public void setUp() throws Exception {
this.url = new URL("http://localhost:" + port + "/test?value=a&value=b&value=c");
}
#Test
public void getHello() throws Exception {
ResponseEntity<String> response = template.getForEntity(url.toString(),
String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Assert.assertEquals(response.getBody(), "a");
System.out.println("response = " + response);
}
}
I then modified your code to accept an array of strings, and only pass the first element to your Response Constructor.
Notice the changes in your code in the signature and return statement.
#GetMapping("/test")
public String search(#RequestParam String[] value) {
System.out.println(value);
return new Response(value[0]);
}
With your test, you can now explore using a List type for your request param and quickly see how the behaviour has changed.

Sending a complex object as a parameter in Resteasy

I am using resteasy, and till now I am just sending and receiving string as parameters and every thing was OK, but now I want to send a complex object ( List<Map<String, ObjectVal>> ) as one of my parameters. My objectVal class has two simple field ( id and value, with getters and setters).
I can find different question and answers for sending objects as parameters but all of them are missing something and not useful for me.
here is my functions with a simple string parameter
#GET
#Path("/isUserAuthorizedToDocument")
public Response isUserAuthorizedToDocumentService(
#QueryParam("userID") String userID){
.............
.............
}
and the client
private ClientRequest req =new ClientRequest(....url with path and ....)
req.queryParameter("userID", user.getUserId());
ClientResponse<Boolean> response = req.get(Boolean.class);
Now I want to send a parameter from my client in the form of List<Map<String,ObjectVal>> and recieve it in my rest function.
My ObjectVal class
#XmlRootElement(name = "objectValueDTO")
public class ObjectValueDTO implements Serializable {
/**
* Id for this class
*/
private static final long serialVersionUID = 164186789404269392L;
// Id on object type
private String objectTypeID = "";
// Selection
private String value = "";
/** Getter and Setters */
#XmlElement
public String getObjectTypeID() {
return objectTypeID;
}
public void setObjectTypeID(String objectTypeID) {
this.objectTypeID = objectTypeID;
}
#XmlElement
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
any help will be appreciated
I may be niave on this. But when you have to send complex parameters, you need to use PUT and send the parameters in the request.

saving variables wp7

Whats the best way to save variables like userid that is stored and reachable from different pages in WP7.
There's the querystring method, but can be kind of a pain to implement.
When navigating, pass the parameter like a HTTP querystring.
Then, on the otherside, check if the key exists, and extract the value. The downside of this is if you need to do more than 1, you need to type it in yourself, and it only supports strings.
So to pass an integer, you'd need to convert it. (And to pass a complex object, you need to take all the pieces you need to recompile it on the other side)
NavigationService.Navigate(new Uri("/PanoramaPage1.xaml?selected=item2", UriKind.Relative));
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
string selected = String.Empty;
//check to see if the selected parameter was passed.
if (NavigationContext.QueryString.ContainsKey("selected"))
{
//get the selected parameter off the query string from MainPage.
selected = NavigationContext.QueryString["selected"];
}
//did the querystring indicate we should go to item2 instead of item1?
if (selected == "item2")
{
//item2 is the second item, but 0 indexed.
myPanorama.DefaultItem = myPanorama.Items[1];
}
base.OnNavigatedTo(e);
}
Here's a sample app that uses a querystring.
http://dl.dropbox.com/u/129101/Panorama_querystring.zip
A easier (and better) idea is to define a variable globally, or use a static class. In App.xaml.cs, define
using System.Collections.Generic;
public static Dictionary<string,object> PageContext = new Dictionary<string,object>;
Then, on the first page, simply do
MyComplexObject obj;
int four = 4;
...
App.PageContext.Add("mycomplexobj",obj);
App.PageContext.Add("four",four);
Then, on the new page, simply do
MyComplexObj obj = App.PageContext["mycomplexobj"] as MyComplexObj;
int four = (int)App.PageContext["four"];
To be safe, you should probably check if the object exists:
if (App.PageContext.ContainsKey("four"))
int four = (int)App.PageContext["four"];
You may use an App level variable (defined in App.xaml.cs) and access it from anywhere within your app. If you want to persist, shove it into Isolated Storage and read it on App launch/activate. There are helpers available to JSon serialize/deserialize your reads/writes from the Isolated Storage.
Check out Jeff's post (here) on tips to use Isolated Storage.
Hope this helps!
Well "best" is always subjective, however, I think an application service is a good candidate for this sort of thing:-
public interface IPhoneApplicationService : IApplicationService
{
string Name {get; set;}
object Deactivating();
void Activating(object state);
}
public class AuthenticationService : IPhoneApplicationService
{
public static AuthenticationService Current {get; private set; }
public void StartService(ApplicationServiceContext context)
{
Current = this;
}
public void StopService()
{
Current = null;
}
public string Name {get; set;}
public object Deactivating()
{
// Return an serialisable object such as a Dictionary if necessary.
return UserID;
}
public void Activating(object state)
{
UserID = (int)state;
}
public int UserID { get; private set; }
public void Logon(string username, string password)
{
// Code here that eventually assigns to UserID.
}
}
You place an instance of this in your App.xaml:-
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
<local:AuthenticationService Name="AuthServ" />
</Application.ApplicationLifetimeObjects>
Now you do need to tweak the App.xaml.cs:-
private void Application_Activated(object sender, ActivatedEventArgs e)
{
var state = PhoneApplicationService.Current.State;
foreach (var service in ApplicationLifetimeObjects.OfType<IPhoneApplicationService>())
{
if (state.ContainsKey(service.Name))
{
service.Activating(state[service.Name]);
}
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
var state = PhoneApplicationService.Current.State;
foreach (var service in ApplicationLifetimeObjects.OfType<IPhoneApplicationService>())
{
if (state.ContainsKey(service.Name))
{
state[service.Name] = service.Deactivating();
}
else
{
state.Add(service.Name, service.Deactivating());
}
}
}
You can now access you UserID anywhere in your app with:-
AuthenticationService.Current.UserID
This general pattern can be used to maintain seperation of key application wide services (you don't load a whole bunch of incohesive properties into your App class). It also provides the hooks for maintaining state between activations which is essential.

Custom Date Format with jax-rs in apache cxf?

I have been googling to figure out how I can customize the Date format when I use jax-rs on apache CXF. I looked at the codes, and it seems that it only support primitives, enum and a special hack that assume the type associated with #FormParam has a constructor with a single string parameter. This force me to use String instead of Date if I want to use FormParam. it is kind of ugly. Is there a better way to do it?
#POST
#Path("/xxx")
public String addPackage(#FormParam("startDate") Date startDate)
{
...
}
Thanks
starting from CXF 2.3.2 registering ParameterHandler will do it. It is also always possible to override the date value (passed as part of the query, etc) using RequestHandler filters for default Date(String) to work
One simple apporach is take parameter as String and parse it in method body to convert it to java.util.Date
Another is create one class having constructor takes on parameter of type String. Perform same thing as I told in first approach.
here is the code for second approach.
#Path("date-test")
public class DateTest{
#GET
#Path("/print-date")
public void printDate(#FormParam("date") DateAdapter adapter){
System.out.println(adapter.getDate());
}
public static class DateAdapter{
private Date date;
public DateAdapter(String date){
try {
this.date = new SimpleDateFormat("dd/MM/yyyy").parse(date);
} catch (Exception e) {
}
}
public Date getDate(){
return this.date;
}
}
}
Hope this helps.
After reading the CXF codes (2.2.5), it is not possible, and it is hardcoded to use the Date(String) constructor, so whatever Date(String) support.
In Apache-cxf 3.0, you can use a ParamConverterProvider to convert a parameter to a Date.
The following code is copied from my answer to this question.
public class DateParameterConverterProvider implements ParamConverterProvider {
#Override
public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
if (Date.class.equals(type)) {
return (ParamConverter<T>) new DateParameterConverter();
}
return null;
}
}
public class DateParameterConverter implements ParamConverter<Date> {
public static final String format = "yyyy-MM-dd"; // set the format to whatever you need
#Override
public Date fromString(String string) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
try {
return simpleDateFormat.parse(string);
} catch (ParseException ex) {
throw new WebApplicationException(ex);
}
}
#Override
public String toString(Date t) {
return new SimpleDateFormat(format).format(t);
}
}

Resources